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按总和问题加入表组的主要内容,如果未能解决你的问题,请参考以下文章