【问题标题】:Combine two sql queries into a single table将两个 sql 查询合并到一个表中
【发布时间】:2019-01-25 22:35:59
【问题描述】:

我有两个 SQL 查询,其中首先使用内连接来根据条件进行匹配,而另一个则不使用。最终,我想要每个查询创建的列之间的差异。我怎样才能做到这一点?

我已经尝试联合和加入一些类似帖子中的查询,但它不起作用。我想知道问题是否与每个查询中的连接有关。

查询 1:

SELECT A.date, COUNT(DISTINCT A.id)
FROM A
INNER JOIN B
ON A.id = B.id AND A.date = B.date
AND B.col1 = 'value1'
LEFT JOIN C on C.key = A.key
WHERE A.col1 = 'value2'
AND C.category = 'cat1'
GROUP BY 1
ORDER BY 1 DESC

查询 2:

SELECT A.date, COUNT(DISTINCT A.id)
FROM A
LEFT JOIN C on C.key = A.key
WHERE A.col1 = 'value2'
AND C.category = 'cat1'
GROUP BY 1
ORDER BY 1 DESC 

【问题讨论】:

  • 你能定义你所说的“差异”吗? 1970-Jan-01 和 1970-Jan-03 之间的“差异”是“2 天”或“是”
  • 您的查询非常相似,可以在一个更短的查询中进行优化。如果您能提供示例数据和预期输出,这将有所帮助...
  • 注意:在这两个查询中,C.category=...WHERE 子句中的存在会破坏LEFT JOIN C(也就是说,它将它变成INNER JOIN)。

标签: sql


【解决方案1】:

c 的左连接实际上变成了内连接,因为它在 NULL 不包括 WHERE 子句中的表达式中使用。所以你可以直接inner joinc和left joinb。然后,您可以在一个 count() 中使用一个案例来仅计算加入了来自 b 的行的实例。从另一个 count() 中减去该值,计算所有出现次数以获得差异。

SELECT a.date,
       count(DISTINCT a.id)
       -
       count(DISTINCT CASE
                        WHEN b.id IS NOT NULL THEN
                          a.id
                      END)
       FROM a
            INNER JOIN c
                       ON c.key = a.key
                          AND c.category = 'cat1'
            LEFT JOIN b
                      ON a.id = b.id
                         AND a.date = b.date
                         AND b.col1 = 'value1'
       WHERE a.col1 = 'value2'
       GROUP BY 1
       ORDER BY 1 DESC;

【讨论】:

    【解决方案2】:
    SELECT A.date, COUNT(DISTINCT A.id)
    FROM A
    INNER JOIN B
    ON A.id = B.id AND A.date = B.date
    AND B.col1 = 'value1'
    LEFT JOIN C on C.key = A.key
    WHERE A.col1 = 'value2'
    AND C.category = 'cat1'
    GROUP BY 1
    ORDER BY 1 DESC
    
    UNION 
    
    SELECT A.date, COUNT(DISTINCT A.id)
    FROM A
    LEFT JOIN C on C.key = A.key
    WHERE A.col1 = 'value2'
    AND C.category = 'cat1'
    GROUP BY 1
    ORDER BY 1 DESC
    

    【讨论】:

      【解决方案3】:

      一个简单的方法是JOIN 两个查询,使用date 列,这在两个查询中都可用:

      SELECT x.date, x.cnt, y.cnt, y.cnt - x.cnt
      FROM 
      (
          SELECT A.date, COUNT(DISTINCT A.id) AS cnt
          FROM A
          INNER JOIN B ON A.id = B.id AND A.date = B.date AND B.col1 = 'value1'
          LEFT JOIN C on C.key = A.key
          WHERE A.col1 = 'value2' AND C.category = 'cat1'
          GROUP BY 1
      ) AS x 
      INNER JOIN (
          SELECT A.date, COUNT(DISTINCT A.id) AS cnt
          FROM A
          LEFT JOIN C on C.key = A.key
          WHERE A.col1 = 'value2' AND C.category = 'cat1'
          GROUP BY 1
      ) AS y ON x.date = y.date
      ORDER BY 1 DESC 
      

      您可能希望根据您的数据布局调整连接类型:

      • LEFT JOIN 如果所有日期在第一个子查询中都可用,但在第二个子查询中可能会丢失
      • RIGHT JOIN 如果情况正好相反
      • FULL OUTER JOIN 如果你想要两端的所有可用日期

      如果您选择上述任何选项,则需要使用COALESCE 来防止当其中一个术语为NULL 时,减法返回NULL

      【讨论】:

        猜你喜欢
        • 2012-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-23
        • 2015-02-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多