【问题标题】:How to replace a subselect with a join in a case statement in SQL?如何在 SQL 的 case 语句中用连接替换子选择?
【发布时间】:2019-04-16 09:41:46
【问题描述】:

我有一个带有 case 语句的 SQL 查询。 case 语句有一个子查询。我想用连接替换(删除)子选择。有可能的?我该怎么做?

查询:

SELECT tablex.Abnumber, CASE WHEN Abdate is not null AND isnull(Abnumber,0) > 1 AND Abdate < (SELECT Abdate FROM t_tablex WHERE Annumber = @Annumber AND Abnumber= @Abnumber-1) THEN 'bla bla' ELSE '' END
FROM t_tablex AS tablex
WHERE (@Annumber IS NULL OR tablex.Annumber= @Annumber)
  AND (@AbnumberIS NULL OR tablex.Abnumber= @Abnumber)

【问题讨论】:

  • 请提供样本数据和期望的结果。需要有关数据的更多信息。
  • 如果你能提供一些数据会很棒。我也对你的桌子的样子很感兴趣。更具体地说,表名、列名以及您拥有的主键和外键。另一个想到的问题是你的局部变量是在哪里设置的。这可能是在存储过程中吗?

标签: sql tsql join subquery


【解决方案1】:
SELECT tablex.Abnumber, 
        CASE WHEN  isnull(Abnumber,0) > 1 AND Abdate < a.Abdate THEN 'bla bla' ELSE '' END  
FROM t_tablex AS tablex 
LEFT JOIN (SELECT Abdate 
           FROM  t_tablex
           WHERE Annumber = @Annumber AND Abnumber= @Abnumber-1
) A ON A.Annumber = tablex.Annumber AND a.Abnumber = tablex.Abnumber
 WHERE tablex.Annumber= @Annumber 
AND  tablex.Abnumber= @Abnumber

【讨论】:

    【解决方案2】:

    我怀疑LAG() 做了你想做的事:

    SELECT x.Abnumber,
           (CASE WHEN x.Abdate is not null AND  
                      x.Abnumber > 1 AND
                      x.Abdate < prev_Abdate
                 THEN 'bla bla'
                 ELSE '' 
            END)
    FROM (SELECT x.*, 
                 LAG(Abdate) OVER (PARTITION BY Annumber ORDER BY Abnumber) as prev_Abdate)
          FROM t_tablex x
         ) x
    WHERE (@Annumber IS NULL OR x.Annumber= @Annumber) AND
          (@Abnumber IS NULL OR x.Abnumber = @Abnumber);
    

    这并不完全等同于您的查询,除非对数据做出了一些假设。但是,我怀疑这实际上是您想要的。

    【讨论】:

      【解决方案3】:

      感谢您的回答。我尝试了一些方法并找到了以下解决方案:

      解决方案1(将子选择替换为内连接):

      SELECT tablex.Abnumber, 
          CASE WHEN tablex.Abdate is not null 
              AND isnull(tablex.Abnumber,0) > 1 
              AND tablex.Abdate < tablex2.Abdate 
          THEN 'bla bla' 
          ELSE '' END 
      FROM t_tablex AS tablex
      INNER JOIN t_tablex as tablex2
          ON tablex.Annumber = tablex2.Annumber
          AND tablex.Abnumber = tablex2.Abnumber + 1 
      WHERE tablex.Annumber = ISNULL( @Annumber, tablex.Annumber)
      AND tablex.Abnumber = ISNULL( @Abnumber, tablex.Abnumber)
      

      解决方案 2(使用 LAG()):

      SELECT base.*
      FROM ( 
          SELECT tablex.Abnumber, 
              CASE WHEN tablex.Abdate is not null 
                  AND tablex.Abnumber > 1 
                  AND tablex.Abdate < LAG( tablex.Abdate, 1 ) OVER ( PARTITION BY tablex.Annumber ORDER BY tablex.Abnumber) 
              THEN 'bla bla' 
              ELSE '' END AS ERG
          FROM t_tablex AS tablex
          WHERE tablex.Annumber = ISNULL( @Annumber, tablex.Annumber )
          AND tablex.Abnumber BETWEEN ISNULL( @Abnumber , tablex.Abnumber) - 1 
          AND ISNULL( @Abnumber, tablex.Abnumber )
          ) base
      WHERE
      base.Abnumber = ISNULL( @Abnumber, base.Abnumber )
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多