【问题标题】:MERGE between 2 tables, one table with 10million rowsMERGE 2张表,一张1000万行的表
【发布时间】:2017-04-13 21:32:46
【问题描述】:

TableA
匹配 / 关键字
0 堆栈溢出
1
1 看看
0 Yandex
1 推特ter
0 脸书
0 Teacher
TableA 共有 1000 万行
关键字列有聚集索引

表B
匹配 / 单词
1
1
1 推特
0 首页
0 辆车
0 铅笔
0 钱
0 天气
0 Her
TableB 总共有 500 行
单词列有聚集索引

我的问题
如果在 TableA keywords 中匹配,我想做一个 sql 查询来匹配 TableB 中的每个 word。并用 1
更新 TableB.match (TableA.keyword like '+TableB.word+'%') (会匹配)

不是中间的关键字匹配; (TableA.keyword like '%'+TableB.word+'%')
例如 Her -> 在 Teacher不会匹配

我尝试使用 MERGE

第一次尝试;
我尝试将关键字与单词匹配并更新 TableB
我得到错误,因为 TableA 中有多个匹配项,并且 MERGE 不允许在目标表 (TableB) 中的一行更新多次

MERGE INTO [TableB] As XB 
USING (Select keyword FROM [TableA]) As XA 
ON XB.word LIKE ''+XA.keyword+'%' 
WHEN MATCHED THEN UPDATE SET XB.match=1;

第二次尝试;
我尝试用关键字匹配单词并更新 TableA
我得到了我想要的,问题是,执行 1000 万个关键字中 500 个单词的查询需要 1 小时 .

MERGE INTO [TableA] As XA 
USING (Select word FROM [TableB]) As XB 
ON XB.word LIKE ''+XA.keyword+'%' 
WHEN MATCHED THEN UPDATE SET XA.match=1;

有没有一个选项可以在 SecondTry 中固定这些查找?

【问题讨论】:

  • 你为什么在这里使用合并?似乎您只有在匹配时才做某事。这应该是一个更新声明。而且无论你如何分割它,性能都将是可怕的。您正在执行通配符搜索,以查找 1000 万行中是否存在 500 个单词。索引在这里根本没有帮助。
  • 那么,如果表 B 中的单词出现在表 a 中的任何位置,您希望它的 match = 1,否则为 0?
  • 并且表 b 中的单词必须在表 a 的开头?
  • 如果有匹配项,您是否还希望表 a 中的 match = 1?
  • 是的,在 TableA 中关键字列开始位置的任意位置。并将 TableB.match 列更新为 1。不,我不想更新 TableA,谢谢

标签: sql-server join merge exists


【解决方案1】:

更新语句足以满足您的要求。请注意,这可能不会很好地执行,因为 SQL 不擅长比较字符串。

declare @a table (match int, keyword varchar(50))
declare @b table (match int, keyword varchar(50))

insert into @a values (0, 'Stackoverflow')
insert into @a values (0, 'Youtube')
insert into @a values (0, 'Google')
insert into @a values (0, 'Yandex')
insert into @a values (0, 'Twitter')
insert into @a values (0, 'Facebook')
insert into @a values (0, 'Teacher')


insert into @b values (0, 'You')
insert into @b values (0, 'Go')
insert into @b values (0, 'Twit')
insert into @b values (0, 'Home')
insert into @b values (0, 'Car')
insert into @b values (0, 'Pencil')
insert into @b values (0, 'Money')
insert into @b values (0, 'Weather')
insert into @b values (0, 'Her')

--commented out because user didn't want this, but it matches the provided data
--update @a
--set match = 1
--where keyword in
--(
--  select 
--      distinct a.keyword
--  from @a a
--  cross apply @b b
--  where a.keyword like b.keyword + '%'
--)

update @b
set match = 1
where keyword in
(
    select 
        distinct b.keyword
    from @a a
    cross apply @b b
    where a.keyword like b.keyword + '%'
)

select *
from @a

select *
from @b

--肖恩编辑-- 以下是您如何将其作为相关子查询来执行,以便您可以使用 EXISTS。

update b
set match = 1
from @b b
where exists
(
    select b.keyword
    from @a a
    where a.keyword like b.keyword + '%'
)

【讨论】:

  • 将“where keyword in”更改为“where exists”将有助于提高性能。
  • @SeanLange 嗯,我试过了,它把所有东西都标记为 1
  • 同意。除了 1000 万行的速度非常慢之外,没有任何代码可以让这一切变得更糟。
  • DForck42 谢谢和@SeanLange 你的代码帮助我在 4-5 秒内执行查询,而不是 MERGE +1 的一个小时谢谢
  • @G.KISA 如果此代码对您有用,那么您应该考虑将其标记为已接受的答案。
猜你喜欢
  • 1970-01-01
  • 2019-10-22
  • 2011-09-30
  • 2019-11-15
  • 2012-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多