#sql #sql-server
Вопрос:
Я имею в виду упражнение по присоединению к sqlzoo, связанное здесь: https://sqlzoo.net/wiki/The_JOIN_operation
Я уже решил это, используя «СЛУЧАЙ, КОГДА», как указано в вопросе, но я просто пытаюсь сделать это по-другому.
ниже приведен мой код, который дал мне правильный ответ во всех столбцах, кроме столбца score2, он показывает тот же результат, что и score1, мне просто было интересно, какую ошибку я совершил в приведенном ниже коде.
SELECT
MDATE,
TEAM1,
COUNT(X.MATCHID) AS SCORE1,
TEAM2,
COUNT(Y.MATCHID) AS SCORE2
FROM GAME
LEFT JOIN GOAL X ON ID = X.MATCHID AND TEAM1 = X.TEAMID
LEFT JOIN GOAL Y ON ID = Y.MATCHID AND TEAM2 = Y.TEAMID
GROUP BY MDATE, TEAM1, TEAM2
Комментарии:
1. Примеры данных и ожидаемые результаты помогут нам помочь вам здесь.
2. Я также настоятельно рекомендую вам использовать псевдонимы всех ваших таблиц и квалифицировать все ваши столбцы;
ID
например, из какой таблицы?3. Ваш вопрос должен быть автономным, не полагаться на внешние ссылки; как указано, вам нужно использовать псевдонимы всех таблиц и столбцов, чтобы он был легко читаем без двусмысленности; Я бы, вероятно, использовал здесь коррелированный подзапрос.
Ответ №1:
Вы неправильно понимаете, как COUNT
это работает.
Он подсчитывает все ненулевые значения, переданные ему. И он не подсчитывает количество MATCHID
в каждой таблице до объединения, он работает только после объединения.
Таким образом , конечный набор результатов после присоединения затем вводится в GROUP BY
, и только после этого COUNT
выполняется. Поскольку MATCHID
значение не равно нулю, для обоих подсчетов получается один и тот же результат.
Вместо этого вам нужно предварительно сгруппироваться, используя или LEFT JOIN
APPLY
SELECT
GAME.MDATE,
GAME.TEAM1,
G1.SCORE1,
GAME.TEAM2,
G2.SCORE2
FROM GAME
LEFT JOIN (
SELECT MATCHID, TEAMID, COUNT(*) SCORE1
FROM GOAL
GROUP BY MATCHID, TEAMID
) G1 ON GAME.ID = G1.MATCHID AND GAME.TEAM1 = G1.TEAMID
LEFT JOIN (
SELECT MATCHID, TEAMID, COUNT(*) SCORE2
FROM GOAL
GROUP BY MATCHID, TEAMID
) G2 ON GAME.ID = G2.MATCHID AND GAME.TEAM2 = G2.TEAMID;
Поочередно
SELECT
GAME.MDATE,
GAME.TEAM1,
G1.SCORE1,
GAME.TEAM2,
G2.SCORE2
FROM GAME
OUTER APPLY (
SELECT COUNT(*) SCORE1
FROM GOAL G1
WHERE GAME.ID = G1.MATCHID AND GAME.TEAM1 = G1.TEAMID
) G1
OUTER APPLY (
SELECT COUNT(*) SCORE2
FROM GOAL G2
WHERE GAME.ID = G2.MATCHID AND GAME.TEAM2 = G2.TEAMID
) G2;
Ответ №2:
WITH xGoalQ
AS
(
SELECT MATCHID, TEAMID , COUNT(1) AS Score
FROM GOAL
GROUP BY MATCHID, TEAMID
)
SELECT
MDATE,
TEAM1,
X.Score AS SCORE1,
TEAM2,
Y.Score AS SCORE2
FROM GAME
LEFT JOIN xGoalQ X ON ID = X.MATCHID AND TEAM1 = X.TEAMID
LEFT JOIN xGoalQ Y ON ID = Y.MATCHID AND TEAM2 = Y.TEAMID
ORDER BY MDATE, TEAM1, TEAM2
или
SELECT
MDATE,
TEAM1,
(SELECT COUNT(1) FROM GOAL WHERE MATCHID = GAME.Id AND TEAMID = GAME.Team1) AS SCORE1,
TEAM2,
(SELECT COUNT(1) FROM GOAL WHERE MATCHID = GAME.Id AND TEAMID = GAME.Team2) AS SCORE2
FROM GAME
ORDER BY MDATE, TEAM1, TEAM2