【问题标题】:IN CLAUSE CONTAIN MANY VALUES - TSQL在子句中包含许多值 - SQL
【发布时间】:2013-07-11 18:22:54
【问题描述】:

我需要你的建议。

我的 T-SQL 查询中有一个 CASE 语句,如下所示:

CASE 
    WHEN PLAN_GIVEN IN ( this list contains 1700 values to compare ) THEN 'P1'
    WHEN PLAN_GIVEN IN ( this list contains 1800 values to compare ) THEN 'P2'  
    ELSE NULL
END AS PLAN_NAME

我无法列出所有 1700 个值 IN ( ) THEN 'P1',因为所有这些值看起来都不好。

我尝试将 1700 个值和 1800 个值保存到 lookup_table 之类的

lookup_table  

columnA = all 1700 values                 
columnB = all 1800 values

并使用了这个查询:

CASE 
    WHEN PLAN_GIVEN IN (SELECT columnA from lookup_table) THEN 'P1'
    WHEN PLAN_GIVEN IN (SELECT columnB from lookup_table) THEN 'P2'  
    ELSE NULL
END AS PLAN_NAME

上面的代码可以运行,但是要花更多的时间来执行将近 10 分钟才能完成执行。

有没有其他方法可以实现这一点?

【问题讨论】:

  • 这 1700 个值从何而来?如果它们来自应用程序,您可以将它们传递给表值参数。或者,您可以向表中添加一列并更新一次 - 将任何符合条件的行设置为 true。现在,只要保持这一点,您的查询现在就可以说 WHERE IsInThisCrazyList = 1。
  • 感谢亚伦的回复!这些值不是来自任何应用程序。我们的客户给了我们这些值来与查询进行比较。我无法更改现有表的结构,因此我将尝试使用表值参数。

标签: sql sql-server performance tsql case


【解决方案1】:

不要使用PLAN_GIVEN IN,而是尝试使用EXISTS

CASE 
    WHEN EXISTS (SELECT NULL from lookup_table WHERE PLAN_GIVEN = columnA) 
         THEN 'P1'
    WHEN EXISTS (SELECT NULL from lookup_table WHERE PLAN_GIVEN = columnB) 
         THEN 'P2'  
ELSE NULL
END AS PLAN_NAME

或者,尝试加入您的查找表并与您的 CASE 表达式中的查找值进行比较:

SELECT ...
       CASE PLAN_GIVEN
           WHEN lookup_table.columnA THEN 'P1'
           WHEN lookup_table.columnB THEN 'P2'  
           ELSE NULL
       END AS PLAN_NAME
       ...
FROM ...
LEFT JOIN lookup_table 
  ON PLAN_GIVEN IN (lookup_table.columnA, lookup_table.columnB)

【讨论】:

  • 感谢马克的回复!!我使用了你的第一种方法,它仍然需要更多时间。我正在尝试你的第二种方法。再次感谢!!
【解决方案2】:

我会将查找表更改为如下所示:

Value  Name
-----  ----
123    P1
456    P1
...    ...
789    P2
...    ...

使用Value 上的聚集索引。

之后,您可以简单地在 LookupTable.Value = <em>otherTable</em>.PLAN_GIVEN 上外连接查找表,然后在 SELECT 子句中拉取 LookupTable.Name,即:

SELECT
  ...
  lookup.Name AS PLAN_NAME,
  ...
FROM
  ...
  LEFT OUTER JOIN LookupTable lookup ON lookup.Value = otherTable.PLAN_GIVEN
WHERE...
...

请注意,我假设查找值是唯一的,考虑到您在 CASE 表达式中处理它们的方式,这在我看来是很自然的。

【讨论】:

    【解决方案3】:

    首先使用@MarkBannister 给出的解决方案之一。其次在你的lookup_table的每一列上放置索引。

     CREATE INDEX IX_lookup_table_A ON lookup_table(columnA)
     CREATE INDEX IX_lookup_table_B ON lookup_table(columnB)
    

    即使lookup_table 是一个临时表,仍然值得花时间添加索引。如果它是一个静态表,那么它的 WELL 值得花时间。

    【讨论】:

      【解决方案4】:

      值得一试

      select 'P1' 
      from table 
      where PLAN_GIVEN IN ( this list contains 1700 values to compare ) 
      union 
      select 'P2' 
      from table 
      where PLAN_GIVEN IN ( this list contains 1800 values to compare ) 
      

      如果 PLAN_GIVEN 有索引,那么这可以使用索引。
      我不认为 CASE 可以使用索引。

      也许是 TVP 而不是在

      【讨论】:

        猜你喜欢
        • 2021-08-19
        • 1970-01-01
        • 1970-01-01
        • 2023-01-06
        • 1970-01-01
        • 1970-01-01
        • 2021-10-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多