SQL查询以呈现NULL行

时间:2019-02-11 12:06:31

标签: mysql sql

我有一个简单表:

Table: pn
id, vender, article, sells, date
01, Peter, bread, 10, 02-01-2019
02, Tom, bread, 3, 10-01-2019
03, Paul, water, 3, 05-01-2019
04, Peter, oil, 5, 16-01-2019
05, Paul, bread, 1, 22-01-2019
06, Tom, oil, 2, 30-01-2019
07, Peter, bread, 1, 27-01-2019
08, Tom, oil, 1, 17-01-2019

我希望有一个查询,该查询将返回特定时间段内针对特定商品的每个供应商的销售。例如:面包和油,介于01-01-2019和31-01-2019之间。 查询结果应为:

Vendor, Article, Sells
Paul, bread, 1
Paul, oil, 0
Peter, bread, 11
Peter, oil, 5
Tom, bread, 3
Tom, oil, 3

我的问题是,由于某些供应商没有特定商品的销售,因此未打印该供应商/商品的行,如下所示:

Vendor, Article, Sells
Paul, bread, 1
Peter, bread, 11
Peter, oil, 5
Tom, bread, 3
Tom, oil, 3

请注意缺少的“保罗,油,0”

我的当前代码如下:

SELECT pn.vendor, pn.article, SUM (pn.sells)
FROM pn
WHERE pn.date BETWEEN  01.01.2019 AND 31.01.2019
   AND (pn.article = 'bread' OR pn.article = 'oil')   
GROUP BY pn.vendor, pn.article
ORDER BY pn.vendor ASC, pn.article ASC

我用ISNULL和COALESC尝试了许多不同的代理,但没有运气。 欢迎任何帮助。

谢谢。

2 个答案:

答案 0 :(得分:3)

使用cross join生成行,然后使用left join引入值。

SELECT v.vendor, a.article, COALESCE(SUM(pn.sells), 0)
FROM (SELECT DISTINCT vendor FROM pn) v CROSS JOIN
     (SELECT DISTINCT article FROM pn) a LEFT JOIN
     pn
     ON pn.vendor = v.vendor AND
        pn.article = a.article AND
        pn.date >= '2019-01-01' AND
        pn.date < '2019-02-01' 
WHERE a.article IN ('bread', 'oil')   
GROUP BY v.vendor, a.article
ORDER BY v.vendor ASC, a.article ASC;

注意:

  • 对日期使用标准日期格式(YYYY-MM-DD在SQL和ISO 8601标准中都是标准)。
  • 使用表别名限定所有列引用。
  • 我不知道familia中的ORDER BY是什么。
  • 在大多数数据库中,您只可以将想要的文章作为a的派生表列出。

答案 1 :(得分:0)

跳过WHERE子句也可以得到Paul。然后使用case表达式进行条件聚合:

SELECT pn.vendor, pn.article,
        SUM (case when pn.date BETWEEN  01.01.2019 AND 31.01.2019
                       and AND (pn.article = 'bread' OR pn.article = 'oil')  then pn.sells
                  else 0 end)
FROM pn
GROUP BY pn.vendor, pn.article
ORDER BY pn.vendor ASC, pn.familia ASC