mysql - 两个左连接 - 重复计数

时间:2011-10-08 19:33:19

标签: mysql sql

长时间用户,第一次发布海报。我发现了类似的问题/答案,通常涉及子查询,但我不确定如何应用于我的情况。

我有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)

编辑:示例:( table1 =参加主题公园的每个人的唯一ID; table2 =每个访客首先访问的景点; table3 =每个访问者访问的第二个景点)。

我想写一个查询来查找7个不同的计数: (1)table1中唯一ID的计数 (2)table2中具有每个可能值的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 =它们的数字应该是两倍(因为我得到的是笛卡尔积?)

有什么建议吗?

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

我猜您的问题是table1中的ID不是唯一的。因此即使它在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

答案 2 :(得分: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;