我有:
CREATE TABLE A (id INT,type int,amount int);
INSERT INTO A (id,type,amount) VALUES (1,0,25);
INSERT INTO A (id,type,amount) VALUES (2,0,25);
INSERT INTO A (id,type,amount) VALUES (3,1,10);
CREATE TABLE B (id INT,A_ID int,txt text);
INSERT INTO B (id,A_id,txt) VALUES (1,1,'abc');
INSERT INTO B (id,A_id,txt) VALUES (2,1,'def');
INSERT INTO B (id,A_id,txt) VALUES (3,2,'xxx');
我运行以下查询:
SELECT min(A.id), SUM(A.amount), COUNT(B.id) FROM A
LEFT JOIN B ON A.id = B.A_id
GROUP BY A.type
我明白了:
min(A.id) SUM(A.amount) COUNT(B.id)
1 75 3
3 10 0
但是我反而希望得到:
min(A.id) SUM(A.amount) COUNT(B.id)
1 50 3
3 10 0
有人可以帮忙吗?实现此精确结果的最佳方法是什么? 我想要group BY类型,并获得分组的A.amount的总和,并获得对应于其外键的所有B的count()。
这是repro:https://www.db-fiddle.com/f/esu13uGLcgFDpX7aEQRMJR/0请运行sql代码。
编辑以添加更多详细信息:如果我删除分组,我们知道结果正确 1、50、2 2、25、1
但是我希望上面的结果,实现它的最佳方法是什么?我想使SUM为TYPE,然后计算与该分组A相关的所有B
答案 0 :(得分:1)
该解决方案的简短版本。它首先在内部查询中计算B_ID,因此我需要对外部查询中的计数求和。
SELECT min(A.id), SUM(A.amount), Sum(Bid) FROM A
LEFT JOIN (select count(id) as Bid, A_id from B group by A_id) as Bcount
ON A.id = Bcount.A_id
GROUP BY A.type
答案 1 :(得分:0)
执行此操作的一种方法是使用ROW_NUMBER()
:
WITH CTE AS (SELECT A.id AS Aid,
A.[type],
A.amount,
B.id AS bid,
txt,
ROW_NUMBER() OVER (PARTITION BY A.id ORDER BY B.id) AS RN
FROM A
LEFT JOIN B ON A.id = B.A_ID)
SELECT MIN(Aid) AS Min_A_ID,
SUM(CASE RN WHEN 1 THEN amount END) AS Amount,
COUNT(bid) AS BCount
FROM CTE
GROUP BY [type];
我还建议您摆脱该text
数据类型并使用varchar(MAX)
。
答案 2 :(得分:0)
当您从1-N关系求和时,可能会发生这种情况。
匹配的记录可以将结果相乘。
例如,当A中的1条记录与B中的2条记录联接时,它返回GROUP BY之前A量的2倍。因此,SUM然后将A.amount加倍。
一种解决方法是使用子查询一对一连接。
并且COUNT DISTINCT可用于计算唯一ID。
因此,这只是获得A的总和的一种方法。
SELECT
q1.type,
q1.min_id,
q2.amount,
COALESCE(q1.totalB, 0) as totalB
FROM
(
SELECT
A.type,
MIN(A.id) AS min_id,
COUNT(DISTINCT B.id) AS totalB
FROM A
LEFT JOIN B ON B.A_id = A.id
GROUP BY A.type
) AS q1
JOIN
(
SELECT
type,
SUM(amount) AS amount
FROM A
GROUP BY type
) AS q2 ON q2.type = q1.type
已针对MySql对SQL进行了测试。但这是可以在几乎所有RDBMS上运行的ANSI标准SQL,包括MS Sql Server。