来自3个表的SQL查询返回不正确的结果

时间:2013-09-22 05:20:36

标签: mysql sql

我在作业中有一个问题,我花了超过40个小时试图解决。 在将两个表连接在一起时,我得到了正确的答案,但是当我添加第三个表时 - 我输了一行,计数不正确。

这找到了正确的答案:

use prime_minister_2013;
select ministry.pm_name, count(*) AS Number_times_PM, ministry.min_begin, ministry.party,deputy_pm.deputy_name
from ministry, deputy_pm
where deputy_pm.min_nr = ministry.min_nr
and ministry.party <> 'ALP'
and min_begin < '1930-01-01'
group by ministry.pm_name;

但当我尝试添加第三个包含总督将在他们当选时的表时,它会丢失其中一行(一个PM)并且其中两行的计数加倍。

我假设我有联接/&amp;或分组不正确!

use prime_minister_2013;
select ministry.pm_name, count(*) AS Number_times_PM, ministry.min_begin, ministry.party,deputy_pm.deputy_name, gg_title, gg_name
from ministry
join deputy_pm
on deputy_pm.min_nr = ministry.min_nr
join governor_general
on governor_general.pm_name = ministry.pm_name 
and ministry.party <> 'ALP'
and min_begin < '1930-01-01'
group by ministry.pm_name;

任何建议都非常感谢 - 截至2013年9月25日


感谢大家的意见 - 请查看以下表格样本:

表:事工

min_nr  pm_name party   min _begin
1   Barton E    Protectionist   1/01/1901
15  Bruce S M   Nationalist 9/02/1923
27  Chifley J B ALP 13/07/1945
28  Chifley J B ALP 1/11/1946
9   Cook J  Liberal 24/06/1913
24  Curtin J J A    ALP 7/10/1941
25  Curtin J J A    ALP 21/09/1943

表:副PM

min_nr  deputy _ name   party
1   Deakin A    Protectionist
2   Lyne W J    Protectionist
3   Hughes W M  ALP
4   McLean A    Protectionist
5   Isaacs I A  Protectionist
6   Hughes W M  ALP
7   Cook J  Free Trade
8   Hughes W M  ALP
9   Forrest J   Liberal

表:总督

GG_name GG_title    GG _begin   GG _end pm_name
Hope J A L  7th Earl of Hopetoun    1/01/1901   9/01/1903   Barton E
Tennyson H  2nd Baron Tennyson  9/01/1903   21/01/1904  Barton E
Northcote H S   Baron Northcote 21/01/1904  9/09/1908   Deakin A
Ward W H    2nd Earl of Dudley  9/09/1908   31/07/1911  Deakin A
Denman T    3rd Baron Denman    31/07/1911  18/05/1914  Fisher A
Munro Ferguson, R C Rt Hon Sir  18/05/1914  6/10/1920   Cook J
Forster H W Baron Forster   6/10/1920   8/10/1925   Hughes W M
Baird J L   Baron Stonehaven    8/10/1925   22/01/1931  Bruce S M
Isaacs I A  Rt Hon Sir  22/01/1931  23/01/1936  Scullin J H
Hore-Ruthven A G A  Brig. Gen, Baron Gowrie 23/01/1936  30/01/1945  Lyons J A
Gloucester H W F A  HRH Prince, Duke of Gloucester  30/01/1945  11/03/1947  Curtin J J A

回应太空狗的建议 - 我试过这个:

use prime_minister_2013;
select ministry.pm_name AS 'PM Name', DATE_FORMAT (ministry.min_begin,'%Y') As 'Ministry Started', ministry.party AS 'Party', deputy_pm.deputy_name AS 'Deputy PM Name', COUNT(DISTINCT ministry.min_begin) AS 'Number of times PM',  gg_title AS 'GG Title', gg_name AS 'GG Name'
from ministry
join deputy_pm
on deputy_pm.min_nr = ministry.min_nr
join governor_general
on governor_general.pm_name = ministry.pm_name 
and ministry.party <> 'ALP'
and min_begin < '1930-01-01'
group by ministry.pm_name;

这给了我:

Barton E    1901    Protectionist   Deakin A    1   2nd Baron Tennyson  Tennyson H
Bruce S M   1923    Nationalist Page  C G   1   Baron Stonehaven    Baird J L
Cook J  1913    Liberal Forrest J   1   Rt Hon Sir  Munro Ferguson, R C
Deakin A    1909    Protectionist   Cook J  3   Baron Northcote Northcote H S
Hughes W M  1916    National Labor  Pearce G F  3   Baron Forster   Forster H W

即将到达 - 但仍然缺少没有GG的PM

1 个答案:

答案 0 :(得分:0)

在没有看到数据的情况下很难提供帮助,但是你要求提出建议,所以这就是我要做的。

首先,检查数据 - 你说有些行消失了,而其他双倍的数量 - 这意味着对于某些PM,数据中没有总督,而对于其他人则有两个。你应该尝试更简单的查询,只需选择一些东西(没有组或COUNT函数)分别连接两个表中的每一个,这样你就可以理解数据了。

你正在做INNER JOINJOIN相当于mysql,IIRC)。因此,你只会获得双方都匹配的结果,如果缺少州长,那么你将失去那一行,所以要尝试的是LEFT JOIN - 首先尝试简单的事情:

USE prime_minister_2013;
SELECT ministry.pm_name, gg_name
FROM ministry
LEFT JOIN governor_general
ON governor_general.pm_name = ministry.pm_name ; 

看看是什么让你(如果连续的gg_name中有空白,只用JOIN再试一次,看看该行消失了)。您还将看到是否存在具有两个GG的PM。

从那里开始,这取决于你实际上想要获得什么结果 - 为了让你的计数正确,你可能想要做COUNT(DISTINCT ministry.min_begin)而不是COUNT(*)。第一个将计算部门开始的不同时间的数量(这将是人的PM的数量或时间)而不是匹配行的数量。

还有其他一些事情要考虑 - 在您的查询中,您只按一行分组,然后您选择的其他字段(ministry.min_begin等)将是(再次,如果我正确地回忆起mysql)从匹配的行中随机抽取 - 这可能不是你想要的。因此,您可能需要考虑MIN(ministry.min_begin)等。

最后,它又取决于您的数据,也许数据存储事物发生变化时的日期 - 例如,如果PM发生变化但GG保持不变,您可能会有几个PM行,但只有一个GG行覆盖所有这些(如果这是一个澳大利亚问题,我认为肯定是这样)。在这种情况下,您将需要在日期的交集处进行JOIN。

但是,我认为应该让你开始,你可以更新这个问题 - 或者如果你必须尝试匹配日期,你可以搜索其他答案,或者问一个单独的问题(顺便说一下,这个答案看起来很有希望:MySQL - Finding time overlaps)。

祝你好运。

修改

我不能从这里测试这个,但是使用LEFT JOIN会回到你的旧行,但我认为你需要更聪明。如果您需要每个PM的GG,那么您不能仅仅pm_name加入表格(因为这只是GG启动时的PM名称)。这实际上取决于您需要的实际数据,一件事就是:

USE prime_minister_2013;
SELECT  ministry.pm_name, count(*) AS Number_times_PM, GG_name
  FROM ministry
  JOIN deputy_pm
    ON deputy_pm.min_nr = ministry.min_nr
  LEFT JOIN governor_general
    ON governor_general.GG_begin <= min_begin AND governor_general.GG_end >= min_begin
   AND ministry.party <> 'ALP'
   AND min_begin < '1930-01-01'
 GROUP by ministry.pm_name, GG_name;

但我认为你的数据是故意制作的,所以它真的取决于你想要找到的东西。您可能需要执行两个查询(或一个带有子查询的查询),因为您可能想知道在不同条件下具有多个GG的PM。

但如果你玩上面的东西,你可能会到达某个地方。