我有一个应用程序可以检查记录的废物类型。系统的一部分允许用户预测他们将回收多少废物,并在报告中列出预测的废物类型,包括预测的废物量和记录的实际废物。
它的工作方式是有一个名为forecastwaste
的表和一个名为wastestream
的表。 wastestream
包含有关实际已回收的废物类型的所有数据,forecastwaste
包含已预测的废物类型。 wastetypes
表包含用户可以选择的可用废物类型的名称。
我有这个SQL语句($contractid
包含合同的id):
SELECT ws.wastetype, SUM(ws.recordedweight) totalWeight, SUM(ws.percent) totalPercent, wt.id, wt.category, wt.defrecycling, fw.tonnes
FROM wastestream ws, wastetypes wt, forecastwaste fw
WHERE ws.contractid = ".$contractid."
AND fw.contractid = ".$contractid."
AND ws.wastetype = wt.id
AND fw.wastetype = wt.id
GROUP BY ws.wastetype
但是,我遇到的问题是,如果forecastewate表中的废弃类型不在wastestream
表中,则查询将不会显示任何内容。我希望得到它,以便如果在wastestream
表中找不到任何结果,查询仍会显示forecastewaste记录,如果找不到任何内容,则返回0
。当前查询不允许这样做。
如何让查询工作以便它能够满足我的需求?
修改
感谢Bandydan我已经重写了查询,所以它现在看起来像这样:
SELECT ws.wastetype, SUM(ws.recordedweight) totalWeight, SUM(ws.percent) totalPercent, wt.id, wt.category, wt.defrecycling, fw.tonnes
FROM c1skips.wastestream ws
LEFT JOIN c1skips.wastetypes wt ON (wt.id = ws.wastetype)
INNER JOIN c1skips.forecastwaste fw ON (wt.id = fw.wastetype)
WHERE fw.contractid = '602'
AND ws.contractid = '602'
GROUP BY ws.wastetype;
我会解释我想要做得更好的事情。
我有一个名为forecastwaste
的表格,在该表格中我有以下数据:
|---------------------------------|
| wastetype | tonnes | contractid |
|-----------|--------|------------|
| 1 | 10 | 602 |
| 2 | 20 | 602 |
| 3 | 50 | 602 |
|-----------|--------|------------|
然后使用此表查看wastestream
表,以查看有多少材料被回收。 wastestream
表格如下所示:
|-----------------------------------------|
| wastetype | recordedweight | contractid |
|-----------|----------------|------------|
| 1 | 2 | 602 |
| 1 | 4 | 602 |
| 2 | 20 | 602 |
|-----------|----------------|------------|
两个表都引用了wastetype
表,该表标识了废弃类型的数字。
使用当前查询,只有当它们显示在wastestream
表中时,它才会返回结果。但是,我想要它,即使wastestream
表中没有记录,它也会返回0。
编辑2
我已将COALESCE
添加到我的查询中,如下所示:
SELECT ws.wastetype, SUM(ws.recordedweight) totalWeight, SUM(ws.percent) totalPercent, wt.id, wt.category, wt.defrecycling,
COALESCE(ws.recordedweight, 0) tonnes
FROM c1skips.wastestream ws
LEFT JOIN c1skips.wastetypes wt ON (wt.id = ws.wastetype)
INNER JOIN c1skips.forecastwaste fw ON (wt.id = fw.wastetype)
WHERE fw.contractid = '602'
AND ws.contractid = '602'
GROUP BY ws.wastetype;
但结果仍然相同。它将是SUM(ws.recordedweight) totalWeight
或SUM(ws.percent) totalPercent
返回wastestream
表中的NULL值,但forecaste
表中会有一个值试图引用它们,但是COALESCE
将不适用。
答案 0 :(得分:1)
您需要在预测废弃物和废弃物类型之间进行内部联接以及左向加入废物流:
SELECT ws.wastetype, SUM(ws.recordedweight) totalWeight, SUM(ws.percent) totalPercent, wt.id, wt.category, wt.defrecycling, fw.tonnes
FROM c1skips.forecastwaste fw
JOIN c1skips.wastetypes wt ON (wt.id = fw.wastetype)
LEFT JOIN c1skips.wastestream ws
ON (ws.contractid = fw.contractid) AND (ws.wastetype = fw.wastetype)
WHERE fw.contractid = '602'
GROUP BY ws.wastetype;
我将 fw.contractid ='602'替换为(ws.contractid = fw.contractid)作为join-condition。现在没有必要在两个地方编写contractid,你可以运行没有WHERE的查询来返回所有行。
编辑:将外部表从废物流更改为预测废物
答案 1 :(得分:0)
我认为你需要使用连接重写那个,然后你就可以使用LEFT JOIN了。它以你需要的方式工作。
我能在几分钟内完成的事情看起来像那样:
SELECT ws.wastetype, SUM(ws.recordedweight) totalWeight, SUM(ws.percent) totalPercent, wt.id, wt.category, wt.defrecycling, fw.tonnes
FROM wastetypes wt
LEFT JOIN wastestream ws ON (wt.id = ws.wastetype)
INNER JOIN forecastwaste fw USING(wt.id = fw.wastetype)
WHERE wt.contractid = ".$contractid."
GROUP BY ws.wastetype
这里我假设您需要来自wt的信息,有关相同类型的信息,ws中存在 MAYBE 的信息以及来自fw的那种类型的信息(肯定存在)。我不确定这是对的,因为我没有桌子可以检查,但我想向你展示整个想法。
查看that question的答案,您将找到解决问题的方法。
答案 2 :(得分:0)
尝试:
SELECT
wt.wastetype, wt.id, wt.category, wt.defrecycling,
SUM(ws.recordedweight) totalWeight, SUM(ws.percent) totalPercent,
COALESCE(fw.tonnes, 0) tonnes
FROM c1skips.wastetypes wt
LEFT JOIN c1skips.wastestream ws ON (wt.id = ws.wastetype)
LEFT JOIN c1skips.forecastwaste fw ON (wt.id = fw.wastetype)
WHERE fw.contractid = '602'
AND ws.contractid = '602'
GROUP BY ws.wastetype;
请注意,FROM
已更改为wastetypes
,wastestream
已移至LEFT JOIN
,且有COALESCE
函数。
答案 3 :(得分:0)
根据您的第二次修改,我建议:
SELECT ws.wastetype, SUM(COALESCE(ws.recordedweight, 0)) totalWeight, SUM(COALESCE(ws.percent, 0)) totalPercent, wt.id, wt.category, wt.defrecycling,
COALESCE(ws.recordedweight, 0) tonnes
FROM c1skips.forecastwaste fw
LEFT JOIN c1skips.wastetypes wt ON (wt.id = fw.wastetype)
LEFT JOIN c1skips.wastestream ws ON (wt.id = ws.wastetype)
WHERE fw.contractid = '602'
AND ws.contractid = '602'
GROUP BY ws.wastetype;
这应该可以通过在总和中使用COALESCE来防止空值,并且继续加入到forecastwaste。