используйте SUM с левым соединением, получите неправильный результат - PullRequest
0 голосов
/ 28 января 2019

Итак, у меня есть:

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

Может кто-нибудь помочь?Как лучше всего достичь этого точного результата?Я хочу, чтобы группа BY типа и получить СУММУ сгруппированных A.amount и получить count () для всех B, соответствующих его внешнему ключу.

вот репро: https://www.db -fiddle.com / f/ esu13uGLcgFDpX7aEQRMJR / 0 пожалуйста, ВЫПОЛНИТЕ код sql.

РЕДАКТИРОВАТЬ, чтобы добавить более подробную информацию: я знаю результат правильный , если я удаляю группу по, мы видим 1, 50, 2 2, 25, 1

Но я ожидаю вышеуказанного результата, как лучше всего его достичь?Я хочу сделать СУММУ ТИПА, а затем сосчитать все B, связанные с этой группой A

Ответы [ 3 ]

0 голосов
/ 28 января 2019

Это может произойти, если вы СУММИТЕ из отношения 1-N.

Соответствующие записи могут умножать результат.

Например, когда 1 запись в A объединяется с 2 в B, она возвращает 2-кратное количество A перед GROUP BY.Таким образом, СУММА затем удваивает A.amount.

Способ обойти это, используя подзапросы, которые объединяются один на один.

И COUNT DISTINCT может использоваться для подсчета уникальныхid's.
Так что это просто способ получить правильную сумму 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

Представление в скрипте БД

SQL проверен на MySql.Но это стандарт SQL ANSI, который будет работать практически на любой СУБД, включая MS Sql Server.

0 голосов
/ 28 января 2019

Просто более короткая версия решения.Сначала он подсчитывает 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
0 голосов
/ 28 января 2019

Один из способов сделать это - использовать 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).

...