MySQL按总和问题加入表组

Posted

技术标签:

【中文标题】MySQL按总和问题加入表组【英文标题】:MySQL joining tables group by sum issue 【发布时间】:2012-08-15 02:32:16 【问题描述】:

我在加入表格时遇到问题,这里是示例表格:

表 A:(30 行)

╔════╦════════════╦═════════════╗ ║ ID ║ 名称 ║ 描述 ║ ╠════╬════════════╬═════════════╣ ║ 1 ║ 类型 ║ Unicode 艺术 ║ ║ 2 ║ 页眉 ║ 电子表格 ║ ║ 3 ║ 自动对齐 ║ 关闭 ║ ╚════╩════════════╩═════════════╝

表 B:(100 行)

╔════╦════════════╦═════════════╦════════╕ ║ ID ║ 名称 ║ 描述 ║ 表 A ║ ╠════╬════════════╬═════════════╬════════╕ ║ 1 ║ 类型 ║ Unicode 艺术 ║ 1 ║ ║ 2 ║ 页眉 ║ 电子表格 ║ 1 ║ ║ 3 ║ 自动对齐 ║ 关闭 ║ 2 ║ ╚════╩════════════╩═════════════╩════════╕

表 C:(8000 行)

╔════╦════════════╦═════════════╦════════╕ ║ ID ║ 文章 ║ 文字 ║ TableB ║ ╠════╬════════════╬═════════════╬════════╕ ║ 1 ║ 类型 ║ Unicode 艺术 ║ 1 ║ ║ 2 ║ 页眉 ║ 电子表格 ║ 1 ║ ║ 3 ║ 自动对齐 ║ 关闭 ║ 2 ║ ╚════╩════════════╩═════════════╩════════╕

表 D:(100 000 行并且还在计数)

╔════╦═══════════╦════════════╦═════════════╦═════ ════╗ ║ ID ║ 日期 ║ 点击次数 ║ 展示次数 ║ TableC ║ ╠════╬═══════════╬════════════╬═════════════╬═════ ════╣ ║ 1 ║ 20120814 ║ 10 ║ 3 ║ 1 ║ ║ 2 ║ 20120815 ║ 13 ║ 5 ║ 1 ║ ║ 3 ║ 20120816 ║ 15 ║ 10 ║ 2 ║ ╚════╩═══════════╩════════════╩═════════════╩═════ ════╝

表 E:(200 000 行并且还在增加)

╔════╦═══════════╦════════════╦═══════════╦═══════ ══╗ ║ ID ║ 日期 ║ 浏览量 ║ 访客 ║ TableC ║ ╠════╬═══════════╬════════════╬═══════════╬═══════ ══╣ ║ 1 ║ 20120814 ║ 10 ║ 3 ║ 1 ║ ║ 2 ║ 20120815 ║ 13 ║ 5 ║ 1 ║ ║ 3 ║ 20120816 ║ 15 ║ 10 ║ 2 ║ ║ 4 ║ 20120817 ║ 8 ║ 7 ║ 2 ║ ║ 5 ║ 20120818 ║ 9 ║ 4 ║ 2 ║ ╚════╩═══════════╩════════════╩═══════════╩═══════ ══╝

我用一条 sql 语句查询这些表:

选择 一个名字, 说明, SUM(D.clicks), 总和(D. 印象数), 总和(E.Views), 总和(电子访客) 从 一种 左连接 B ON A.ID=B.TableA 左连接 C ON B.ID=C.TableB 左连接 D ON C.ID=D.TableC 左连接 E ON C.ID=E.TableC 通过...分组 援助

问题是查询返回的表 D 和表 E 的 SUM 无效 但是,如果在个别查询中查询表 D 和表 E,我会得到正确的值:

选择 一个名字, 说明, SUM(D.clicks), 总和(D. 展示次数) 从 一种 左连接 B ON A.ID=B.TableA 左连接 C ON B.ID=C.TableB 左连接 D ON C.ID=D.TableC 通过...分组 援助

编辑 1: 我尝试过右连接、连接、左外连接,但都没有工作, 当然,我可能在错误的地方使用了这些。 但是在我得到“所有包含”的第一个语句中,值相乘 比实际高出数千倍。

【问题讨论】:

尚未阅读您的问题,但对表格艺术 +1。 B 与 A 有什么关系? C 到 B 也一样? 【参考方案1】:

您需要将 D 表和 E 表都展平。那我想 A 和 B 只是 C 的查找,所以没有必要对 A 做 GROUP BY:http://www.sqlfiddle.com/#!2/fccf1/8

我去除了噪音(A 和 B),因为我(还)看不到 A 和 B 如何与汇总 C 的信息相关

试试这个:

SELECT
       C.Article,
       C.Text,

       COALESCE(D.ClicksSum,0) AS ClicksSum,
       COALESCE(D.ImpressionsSum,0) AS ImpressionsSum,

       COALESCE(E.ViewsSum,0) AS ViewsSum,
       COALESCE(E.VisitorsSum,0) AS VisitorsSum
FROM 
       C

       LEFT JOIN 
       (
         SELECT TableC, SUM(Clicks) AS ClicksSum, SUM(Impressions) AS ImpressionsSum
         FROM D
         GROUP BY TableC
       ) D ON C.ID=D.TableC

       LEFT JOIN 
       (
         SELECT TableC, SUM(Views) AS ViewsSum, SUM(Visitors) AS VisitorsSum
         FROM E
         GROUP BY TableC       
       ) E ON C.ID=E.TableC

输出:

|    ARTICLE |        TEXT | CLICKSSUM | IMPRESSIONSSUM | VIEWSSUM | VISITORSSUM |
----------------------------------------------------------------------------------
|       Type | Unicode Art |        23 |              8 |       23 |           8 |
|     Header | Spreadsheet |        15 |             10 |       32 |          21 |
| Auto Align |         Off |         0 |              0 |        0 |           0 |

请注意,我没有在我的 sqlfiddle 帖子中手动输入这些架构,我使用 sqlfiddle 的 Text to DDL

我喜欢http://sqlfiddle.com,它的Text to DDL甚至可以从你的ASCII艺术中解析出数据ツ


在看到您更明确的目标(来自您的评论)后,可能是这样:http://www.sqlfiddle.com/#!2/fccf1/13

SELECT
       A.Name, A.Description,

       COALESCE(SUM(D.ClicksSum),0) AS ClicksSum,
       COALESCE(SUM(D.ImpressionsSum),0) AS ImpressionsSum,

       COALESCE(SUM(E.ViewsSum),0) AS ViewsSum,
       COALESCE(SUM(E.VisitorsSum),0) AS VisitorsSum
FROM 
       C

       LEFT JOIN 
       (
         SELECT TableC, SUM(Clicks) AS ClicksSum, SUM(Impressions) AS ImpressionsSum
         FROM D
         GROUP BY TableC
       ) D ON C.ID=D.TableC

       LEFT JOIN 
       (
         SELECT TableC, SUM(Views) AS ViewsSum, SUM(Visitors) AS VisitorsSum
         FROM E
         GROUP BY TableC       
       ) E ON C.ID=E.TableC

       RIGHT JOIN B ON B.ID = C.TableB
       RIGHT JOIN A ON A.ID = B.TableA

GROUP BY A.ID

输出:

|       NAME | DESCRIPTION | CLICKSSUM | IMPRESSIONSSUM | VIEWSSUM | VISITORSSUM |
----------------------------------------------------------------------------------
|       Type | Unicode Art |        38 |             18 |       55 |          29 |
|     Header | Spreadsheet |         0 |              0 |        0 |           0 |
| Auto Align |         Off |         0 |              0 |        0 |           0 |

上述方法可能仍会产生笛卡尔积,先将 SubCategory(B) 展平,然后再将其分组到 Category(A):http://www.sqlfiddle.com/#!2/fccf1/19

SELECT 
  A.Name, A.Description,
  COALESCE(SUM(B.ClicksSum),0) AS ClicksSum,
  COALESCE(SUM(B.ImpressionsSum),0) AS ImpressionsSum,
  COALESCE(SUM(B.ViewsSum),0) AS ViewsSum,
  COALESCE(SUM(B.VisitorsSum),0) AS VisitorsSum
FROM A
LEFT JOIN
(

  SELECT 
    B.ID, B.TableA,
    SUM(C.ClicksSum) AS ClicksSum,
    SUM(C.ImpressionsSum) AS ImpressionsSum,
    SUM(C.ViewsSum) AS ViewsSum,
    SUM(C.VisitorsSum) AS VisitorsSum
  FROM B
  LEFT JOIN
  (

    SELECT
      C.TableB,

      D.ClicksSum,
      D.ImpressionsSum,

      E.ViewsSum,
      E.VisitorsSum
    FROM 
    C

    LEFT JOIN 
    (
      SELECT TableC, SUM(Clicks) AS ClicksSum, SUM(Impressions) AS ImpressionsSum
      FROM D
      GROUP BY TableC
    ) D ON C.ID=D.TableC

    LEFT JOIN 
    (
      SELECT TableC, SUM(Views) AS ViewsSum, SUM(Visitors) AS VisitorsSum
      FROM E
      GROUP BY TableC       
    ) E ON C.ID=E.TableC

  ) C ON C.TableB = B.ID
  GROUP BY B.ID

) B ON B.TableA = A.ID
GROUP BY A.ID

输出:

|       NAME | DESCRIPTION | CLICKSSUM | IMPRESSIONSSUM | VIEWSSUM | VISITORSSUM |
----------------------------------------------------------------------------------
|       Type | Unicode Art |        38 |             18 |       55 |          29 |
|     Header | Spreadsheet |         0 |              0 |        0 |           0 |
| Auto Align |         Off |         0 |              0 |        0 |           0 |

【讨论】:

您可以认为表 A 为类别,表 B 为子类别,表 C 为产品,表 D 为产品广告数据“广告统计”,表 E 为产品访问数据“包括所有访问”。我需要总结一下每个类别的表现如何 感谢您使用修订版 2 :) BTW 可能想要添加缺少的 AS,以防有人在此之后阅读并使用它。 Rev2 缺少 AS ImpressionsSum 所以当我谈论修订时,在这种情况下 r2 与 r3 可能会出现问题。我正在使用 php,所以声明的长度并不重要。不需要凭记忆记住:) 欢迎 :-) 忽略,现在添加AS【参考方案2】:

表 D 和表 E 都通过表 C 链接到其余表。因此,您的第一个查询给出了表 D 中的所有行乘以表 E 中的所有行的笛卡尔积,并且 SUM 函数聚合了这个笛卡尔积。可能您还必须按表 C 分组,而不仅仅是按表 A。

【讨论】:

我也想过,但是随后查询返回表A值的次数与表C中表A的数据一样多,并为每个表C值单独计算总和。留给我子查询之类的选项?还有什么?

以上是关于MySQL按总和问题加入表组的主要内容,如果未能解决你的问题,请参考以下文章

从同一日期加入总和

Mysql按多行总和/或嵌套总和排序?

按一个字段从表组中获取所有值

mysql用总和加入3个表给出错误的结果

MYSQL按日期累积总和[重复]

将多个表组合成单独的行和列