【问题标题】:T-SQL | Better alternative to WHERE NOT EXISTST-SQL | WHERE NOT EXISTS 的更好替代方案
【发布时间】:2017-07-04 15:10:18
【问题描述】:

我有以下查询:

INSERT INTO [Table A]  ([student_name], [class_id],[contact_detail], [birth_date],[note_average])
            SELECT [student_name] = case when CHARINDEX('.', [student_name])>0 then LEFT([student_name],CHARINDEX('.', [student_name])-1)
                        else [student_name] end
                        ,[class_id]
                        ,case when reverse(SUBSTRING(REVERSE([contact_detail]),1,CHARINDEX(':', REVERSE([contact_detail])))) like ':' 
                                        then ([contact_detail] + '|')
                                        else    [contact_detail]
                                        end as [contact_detail]
                         ,[birth_date]
                         ,CAST([note_average] AS decimal(13,2)) as [note_average]
                         ,GETDATE()
            FROM [Table A] 
            WHERE CAST([birth_date] AS DATE) <= CAST(GETDATE() AS DATE)
                    AND LEN([student_name]) >= 5
                    AND NOT EXISTS
                            (
                      SELECT [student_name]
                                              ,[class_id]
                                              ,[contact_detail]
                                              ,[birth_date]
                      FROM [Table A]  a
                      WHERE  '%' + ods.[student_name] + '%' LIKE a.[student_name]
                                AND '%' +  ods.[class_id] + '%'  LIKE a.[class_id]
                                AND '%' + ods.[contact_detail] + '%' LIKE a.[contact_detail]
                                AND ods.[birth_date] = a.[birth_date]
                            )
GO

我不想插入重复的值,而且我的表中没有键。我的问题是:这个查询需要很多时间来插入新值。我正在尝试插入 1000000 行。

我有哪些选择?

非常感谢!

【问题讨论】:

  • 我相信将 Not Exists 子句中的 select 替换为 SELECT 'x' From... 会更好一些,因为一旦找到第一个匹配项就会转储。
  • @John_Rodgers - 你真的想使用 LIKE 进行比较吗?您是在寻找完全匹配还是类似匹配?尤其是像“class_id”这样的东西。
  • 字段 [student_name],[class_id],[contact_detail],[birth_date] 是我表的业务键。这就是为什么我把所有的比较
  • @John_Rodgers - 这是有道理的,我只是质疑使用 LIKE 与 equals 进行优化。换句话说,只有在真正需要时才使用 LIKE。

标签: sql-server tsql staging-table


【解决方案1】:

假设您真的想匹配完全重复的匹配项,请尝试以下操作:

INSERT INTO [Table A]  ([student_name], [os_name], [class_id],[contact_detail], [birth_date],[note_average])
    SELECT ods.[student_name] = case when CHARINDEX('.', ods.[student_name])>0 then LEFT(ods.[student_name],CHARINDEX('.', ods.[student_name])-1)
            else ods.[student_name] end
        ,ods.[class_id]
        ,case when reverse(SUBSTRING(REVERSE(ods.[contact_detail]),1,CHARINDEX(':', REVERSE(ods.[contact_detail])))) like ':' 
            then (ods.[contact_detail] + '|')
            else    ods.[contact_detail]
            end as [contact_detail]
         ,ods.[birth_date]
         ,CAST(ods.[note_average] AS decimal(13,2)) as ods.[note_average]
         ,GETDATE()
    FROM [Table A] ods
    OUTER JOIN [Table A] a ON ods.[student_name] = a.[student_name]
        AND ods.[os_name] = a.[os_name]
        AND ods.[class_id] = a.[class_id]
        AND ods.[contact_detail] = a.[contact_detail]
        AND ods.[birth_date] = a.[birth_date]
    WHERE CAST(ods.[birth_date] AS DATE) <= CAST(GETDATE() AS DATE)
        AND LEN(ods.[student_name]) >= 5
        -- Only include when no matching duplicate is found.
        AND a.[student_name] IS NULL

如果你愿意,你可以坚持使用子查询而不是存在,这也可以,但使用 SELECT 0 或类似的而不是选择所有这些列,这不是必需的。我相信,将比较从 LIKE 更改为 = 会为您提供所需的结果,并在必要时使用索引优化查询。

AND NOT EXISTS
(
  SELECT 0
  FROM [Table A]  a
  WHERE  ods.[student_name] = a.[student_name]
            AND ods.[os_name] = a.[os_name]
            AND ods.[class_id] = a.[class_id]
            AND ods.[contact_detail] = a.[contact_detail]
            AND ods.[birth_date] = a.[birth_date]
        )

一旦您的查询正常工作,如果您需要更好的性能,您可以考虑添加索引。您也许可以在 [birth_date] 或 [student_name] 上添加索引以获得可接受的查询性能。

【讨论】:

  • EXISTS 子句忽略SELECT 中的列列表。所以SELECT 0 毫无意义。如果你想要一些特别的东西,你可以写EXISTS( SELECT 1 / 0 - 它仍然可以工作。
  • @Alex - 完全同意你的看法。没关系,这就是我想要表达的意思。虽然也许我的例子很糟糕(但这是我通常使用的)。
猜你喜欢
  • 2018-11-15
  • 1970-01-01
  • 2016-04-19
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多