【问题标题】:Combine SQL queries组合 SQL 查询
【发布时间】:2015-02-13 15:18:38
【问题描述】:

我正在尝试将两个非常相似的 SQL 查询与不同的日期范围结合起来,以生成一个输出表。 (将本周的结果与去年相应的一周进行比较。)

我对 SO 进行了一些搜索,发现了一些类似的问题(例如 this one),但仍然没有设法让这个工作:

这两个查询是:

SELECT
    [arrpoint]  
    ,COUNT([arrpoint]) AS NumberOfTimesTW
FROM  [groups] tb1
    INNER JOIN [fileinfo] tb2 ON tb1.op_name = tb2.[operator]
    INNER JOIN [costs] tb4 ON tb2.[fileno] = tb4.[fileno]
WHERE 
    [bedbank] = 1 
    AND [booked] >= DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
GROUP BY [ arrpoint] HAVING (COUNT([arrpoint])>1)
ORDER BY NumberOfTimesTW DESC

和:

SELECT
    [arrpoint]  
    ,COUNT([arrpoint]) AS NumberOfTimesTW
FROM  [groups] tb1
    INNER JOIN [fileinfo] tb2 ON tb1.op_name = tb2.[operator]
    INNER JOIN [costs] tb4 ON tb2.[fileno] = tb4.[fileno]
WHERE 
    [bedbank] = 1 
    AND [booked] >= DateAdd(wk,-52,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
    AND [booked] <= DateAdd(wk,-51,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
GROUP BY [ arrpoint] HAVING (COUNT([arrpoint])>1)
ORDER BY NumberOfTimesTW DESC

这些输出:

arrpoint | NumberOfTimesTW
  abc    |        3
  def    |        2

和:

arrpoint | NumberOfTimesTWLY
  ghi    |        5
  klm    |        4
  abc    |        1

我希望得到的是这样的:

arrpoint | NumberOfTimesTW | NumberOfTimesTWLY
  abc    |       3         |          1
  def    |       2         |
  ghi    |                 |          5
  klm    |                 |          4

对 SQL 了解不多,我原本以为只要在两个查询之间加上 UNION 就可以实现这一点,但没有运气。

谁能给我一些关于如何实现这一点的指导?

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    在聚合中使用 Case 来简化查询

    SELECT
        [arrpoint]  
        ,COUNT( case when [booked] >= DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
            THEN [arrpoint]
            END) AS NumberOfTimesTW
        , COUNT(CASE WHEN ([booked] >= DateAdd(wk,-52,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
        AND [booked] <= DateAdd(wk,-51,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)))
            THEN [arrpoint]
            END) AS NumberOfTimesTWLY
    FROM  [groups] tb1
        INNER JOIN [fileinfo] tb2 ON tb1.op_name = tb2.[operator]
        INNER JOIN [costs] tb4 ON tb2.[fileno] = tb4.[fileno]
    WHERE 
        [bedbank] = 1 
    AND (
        [booked] >= DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0)
        OR(
                [booked] >= DateAdd(wk, - 52, DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0))
                AND [booked] <= DateAdd(wk, - 51, DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0))
                )
            )
    GROUP BY [ arrpoint] HAVING (COUNT([arrpoint])>1)
    ORDER BY NumberOfTimesTW DESC
    

    【讨论】:

    • 这是我将使用的方法,但在 where 子句中过滤行可能是明智的,扫描不会被 COUNT 列计算的行似乎没什么意义
    • @GarethD 我错过了。现在更新了代码。谢谢。
    • 这绝对是一种享受。非常感谢。 =)
    【解决方案2】:

    您可以在第二个查询中使用完全联接(假设您想要两个表中的所有值)

    select  a.[arrpoint], NumberOfTimesTW, NumberOfTimesTW1 
    from
    (
    (SELECT
        [arrpoint]  
        ,COUNT([arrpoint]) AS NumberOfTimesTW
    FROM  [groups] tb1
        INNER JOIN [fileinfo] tb2 ON tb1.op_name = tb2.[operator]
        INNER JOIN [costs] tb4 ON tb2.[fileno] = tb4.[fileno]
    WHERE 
        [bedbank] = 1 
        AND [booked] >= DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
    GROUP BY [ arrpoint] HAVING (COUNT([arrpoint])>1)
    ORDER BY NumberOfTimesTW DESC) as a 
    full join
    (SELECT
        [arrpoint]  
        ,COUNT([arrpoint]) AS NumberOfTimesTW1
    FROM  [groups] tb1
        INNER JOIN [fileinfo] tb2 ON tb1.op_name = tb2.[operator]
        INNER JOIN [costs] tb4 ON tb2.[fileno] = tb4.[fileno]
    WHERE 
        [bedbank] = 1 
        AND [booked] >= DateAdd(wk,-52,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
        AND [booked] <= DateAdd(wk,-51,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
    GROUP BY [ arrpoint] HAVING (COUNT([arrpoint])>1)
    ORDER BY NumberOfTimesTW DESC) as b)
    on a.[arrpoint] =b.[arrpoint] 
    

    【讨论】:

      【解决方案3】:
      with a as (
      SELECT
          [arrpoint]  
          ,COUNT([arrpoint]) AS NumberOfTimesTW
      FROM  [groups] tb1
          INNER JOIN [fileinfo] tb2 ON tb1.op_name = tb2.[operator]
          INNER JOIN [costs] tb4 ON tb2.[fileno] = tb4.[fileno]
      WHERE 
          [bedbank] = 1 
          AND [booked] >= DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
      GROUP BY [ arrpoint] HAVING (COUNT([arrpoint])>1)
      )
      ,b as (
      SELECT
          [arrpoint]  
          ,COUNT([arrpoint]) AS NumberOfTimesTW
      FROM  [groups] tb1
          INNER JOIN [fileinfo] tb2 ON tb1.op_name = tb2.[operator]
          INNER JOIN [costs] tb4 ON tb2.[fileno] = tb4.[fileno]
      WHERE 
          [bedbank] = 1 
          AND [booked] >= DateAdd(wk,-52,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
          AND [booked] <= DateAdd(wk,-51,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
      GROUP BY [ arrpoint] HAVING (COUNT([arrpoint])>1)
      )
      select 
        [arrpoint]
        ,a.NumberOfTimesTW
        ,b.NumberOfTimesTW as NumberOfTimesTWLY
      from a
      full join b
        on a.[arrpoint] = b.[arrpoint]
      

      【讨论】:

      • 这个答案是正确的(除了你不能在派生表中使用 ORDER BY 的事实),但我看不出任何人会发现它有用。根本没有解释你做了什么,只有代码的答案很少是好的答案。
      • 我同意订单,我什至没有看到它,因为它是他代码的副本。我总是在需要解释的地方给出解释。现在,解释一下完全加入..好吧..我认为没有必要这样做。但是仇恨者会讨厌:)
      • 正如您所说,这是一个相当简单的答案,因此您不必提供论文,但只需简短的解释即可使答案更容易理解。可以简单到“我已经从问题中提取了两个单独的查询,并将每个查询放在Common table expression 中,最后我使用full join 来组合这两个数据集。” - 只有当你知道答案时,答案才会显而易见!
      • 我不会说我是一个仇恨者,我认为我以前没有与你有过任何互动,而且我的总票数中只有不到 10% 是反对票。我只是认为这个网站不仅仅是为了回答问题的人的利益,其他人也会有类似的问题并最终出现在这里,除非他们有相同的数据库,否则这个答案是无用的,而如果你讨论的基础知识你所做的下一个人可以将相同的原则应用于他们的问题。仅代码答案的问题是discussed on Meta extensively
      猜你喜欢
      • 2021-01-21
      • 1970-01-01
      • 2016-09-28
      • 2012-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-20
      • 2012-08-30
      相关资源
      最近更新 更多