即使在相关表中找不到相关记录,也从一个表中检索所有记录

时间:2013-09-13 22:55:17

标签: mysql sql cakephp-2.0

我有一个应用程序可以检查记录的废物类型。系统的一部分允许用户预测他们将回收多少废物,并在报告中列出预测的废物类型,包括预测的废物量和记录的实际废物。

它的工作方式是有一个名为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) totalWeightSUM(ws.percent) totalPercent返回wastestream表中的NULL值,但forecaste表中会有一个值试图引用它们,但是COALESCE将不适用。

4 个答案:

答案 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已更改为wastetypeswastestream已移至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。