2011-10-08 63 views
1

长时间用户,第一次张贴海报。我发现了类似的问题/答案,通常涉及子查询,但我不知道如何适用于我的情况。mysql - 两个左连接 - 双重计数

我有3个表:

table1 
id 

table2 
id | val (each id has 1 of 3 possible values) 

table3 
id | val (each id has 1 of 3 possible values) 

编辑:例如:(表1 =每个人的唯一的ID谁参加了一个主题公园,表2 =每个访问者访问了哪些景点第一;表3 =其吸引每个访问者访问第二)。

我想编写一个查询查找7个不同的计数: (1)在表1的唯一ID的数量 (2)让每个可能的值在表2 ID数的计数(3具有每一个可能值的表3中的ID的数量)计数

我的MySQL查询:

SELECT 
    count(DISTINCT table1.id) AS x1, 
    SUM(IF(table2.val='1'),1,0)) AS x2, 
    SUM(IF(table2.val='2'),1,0)) AS x3, 
    SUM(IF(table2.val='3'),1,0)) AS x4, 
    SUM(IF(table3.val='1'),1,0)) AS x5, 
    SUM(IF(table3.val='2'),1,0)) AS x6, 
    SUM(IF(table3.val='3'),1,0)) AS x7 
FROM 
    table1 
LEFT JOIN 
    table2 ON table1.id=table2.id 
LEFT JOIN 
    table3 ON table1.id=table3.id 

结果:

X1 =正确的(因为DISTINCT)

X2,X3,X4 =正确

X5,X6,X7 = TWICE他们应该是多少(因为我得到笛卡尔积?)

有什么建议?

+0

您是否考虑过在子查询中单独计算表,然后连接两个子查询的结果? –

+0

这可能是我需要做的,但是我从来没有做过再次选择,也不知道如何以这种方式重新编写我的查询。 – egret

+0

用户错误。原来我在表2中有重复的记录.ID应该是唯一的,但不能强制在表定义中。因此重复计算。感谢所有对此评论的人。尝试每一个建议帮助我理解发生了什么。 – egret

回答

1

我的猜测是你的问题是,该编号在table1中不是唯一的。因此,尽管它在table2/3(根据您的描述)中是唯一的,但table2/3中的每一行都连接到table1中的两行,因此计数两次。与左连接无关,正常的内连接会有同样的问题。

如果MySQL(我不知道真正的好),让你做内联的意见,如Oracle的话,那么你可以写你的查询作为解决这个问题:

SELECT 
    count(view1.id)    AS x1, 
    SUM(IF(table2.val='1'),1,0)) AS x2, 
    SUM(IF(table2.val='2'),1,0)) AS x3, 
    SUM(IF(table2.val='3'),1,0)) AS x4, 
    SUM(IF(table3.val='1'),1,0)) AS x5, 
    SUM(IF(table3.val='2'),1,0)) AS x6, 
    SUM(IF(table3.val='3'),1,0)) AS x7 
FROM 
    ( SELECT DISTINCT table1.id 
     FROM table1 
    ) view1 
LEFT JOIN 
    table2 ON view1.id=table2.id 
LEFT JOIN 
    table3 ON view1.id=table3.id 
+0

表1中的ID是唯一的。例如:(table1 =参加主题公园的每个人的唯一ID; table2 =每个参观者首先参观的吸引力; table3 =每个参观者参观的吸引力次之)。我将编辑我的原始帖子以添加此(重要/有用)信息。 – egret

+0

用户错误。原来我在表2中有重复的记录.ID应该是唯一的,但不能强制在表定义中。因此重复计算。这可能是最正确的答案,因为它确定了id不是唯一的可能性。谢谢。 – egret

0

我会删除每个重复表:

SELECT 
    count(t1.id) AS t1, 
    SUM(IF(t2.val=1,1,0)) AS t21, 
    SUM(IF(t2.val=2,1,0)) AS t22, 
    SUM(IF(t2.val=3,1,0)) AS t23, 
    SUM(IF(t3.val=1,1,0)) AS t31, 
    SUM(IF(t3.val=2,1,0)) AS t32, 
    SUM(IF(t3.val=3,1,0)) AS t33 
FROM (SELECT DISTINCT * FROM table1) as t1 
JOIN (SELECT DISTINCT * FROM table2) as t2 ON t1.id=t2.id 
JOIN (SELECT DISTINCT * FROM table3) as t3 ON t1.id=t3.id; 
+0

我赞赏这个建议,但没有解决重复计算。 – egret

2

您将得到笛卡尔结果。由于您没有显示每个“ID”有多少“1”,“2”或“3”计数,只需从这些表中自行选择sum()。由于没有分组的总和将总是产生一条记录,所以不需要任何连接,并且它将拉取每个总结的一条记录的结果而不会产生笛卡尔结果。由于您的原始查询是LEFT JOIN的其他人,该ID将已经存在于表1,所以为什么在每个子表中重新查询计数不同。

SELECT 
     SumForTable1.x1, 
     SumForTable2.x2, 
     SumForTable2.x3, 
     SumForTable2.x4, 
     SumForTable3.x5, 
     SumForTable3.x6, 
     SumForTable3.x7 
    FROM 
     (select count(DISTINCT table1.id) AS x1 
      from table1) SumForTable1, 

     (select SUM(IF(table2.val='1'), 1, 0)) AS x2, 
       SUM(IF(table2.val='2'), 1, 0)) AS x3, 
       SUM(IF(table2.val='3'), 1, 0)) AS x4 
      from table2) SumForTable2, 

     (select SUM(IF(table3.val='1'), 1, 0)) AS x5, 
       SUM(IF(table3.val='2'), 1, 0)) AS x6, 
       SUM(IF(table3.val='3'), 1, 0)) AS x7 
      from table3) SumForTable3 
+0

这将在MySQL中工作,但您可能想写'CROSS JOIN'而不是'JOIN'来指出这些连接真的是什么。 –

+0

我认为“笛卡儿结果”是重复计数的原因。我必须为table1中的每个id计算一次table3记录,并且每次在表2中显示相同的id。但是,我无法让您的示例执行。我尝试了一些东西 - 重新写了几个方法 - 但仍然没有运气。 – egret

+0

@egret,对不起,我知道你已经有你的答案明显解决了,但我改变了这一点。由于没有“JOIN”进入,我只用逗号分隔FROM来源,这将允许笛卡尔1:1:1全部合并在一起。 – DRapp