Различные соединения SQL не имеют никакого значения для результата - PullRequest
4 голосов
/ 26 мая 2010

Я пытаюсь написать быструю (ха!) Программу, чтобы организовать часть моей финансовой информации. В идеале мне нужен запрос, который вернет все записи с финансовой информацией в них из таблицы A. Должна быть одна строка для каждого месяца, но в тех случаях, когда в течение месяца не было транзакций, запись не будет. Я получаю такие результаты:


SELECT Period,Year,TotalValue FROM TableA WHERE Year='1997'

Результат:

Period Year  TotalValue
1      1997  298.16
2      1997  435.25
4      1997  338.37
8      1997  336.07
9      1997  578.97
11     1997  361.23

Присоединяясь к таблице (в данном случае к представлению View), которая просто содержит поле Period со значениями от 1 до 12, я ожидаю получить что-то вроде этого:


SELECT p.Period,a.Year,a.TotalValue
FROM Periods AS p
LEFT JOIN TableA AS a ON p.Period = a.Period
WHERE Year='1997'

Результат:

Period Year  TotalValue
1      1997  298.16
2      1997  435.25
3      NULL  NULL
4      1997  338.37
5      NULL  NULL
6      NULL  NULL
7      NULL  NULL
8      1997  336.07
9      1997  578.97
10     NULL  NULL
11     1997  361.23
12     NULL  NULL

То, что я на самом деле получаю, - это один и тот же результат, независимо от того, как я присоединяюсь к нему (кроме CROSS JOIN, который сводит с ума, но это действительно совсем не то, что я хотел в любом случае, просто чтобы увидеть, делают ли разные объединения хоть что-нибудь) , То есть, нет записей NULL, он возвращает только те записи, которые существуют с соответствующими периодами в Таблице A, вместо 12 записей от 1 до 12 независимо. LEFT JOIN, RIGHT JOIN, INNER JOIN - все не могут предоставить ожидаемые записи NULL.

Есть ли что-то очевидное, что я делаю неправильно в JOIN? Имеет ли значение, что я присоединяюсь к View?


Редактировать На примере Марка Байерса я попробовал следующее:

SELECT p.Period,a.Year,a.TotalValue
FROM Periods AS p
LEFT JOIN TableA AS a ON (p.Period = a.Period) AND (a.Year = '1997')

Результат:

Period Year  TotalValue
1      1997  298.16
2      1997  435.25
4      1997  338.37
8      1997  336.07
9      1997  578.97
11     1997  361.23

Он фактически получает тот же результат другим способом, но не получает ожидаемые значения NULL для 3,5,6,7 и т. Д.


Большое спасибо Марку Байерсу за помощь в достижении окончательного решения, которое для записи было:

SELECT p.Period, a.YEAR, SUM(a.Value) as TotalValue
FROM
    Periods as p
LEFT JOIN
    TableA as a
    ON d.Period = p.Period AND a.Year = '1997'
GROUP BY p.Period,a.Year,a.PERIOD
ORDER BY p.Period,a.Year;

На практике также существует поле LedgerID, которое группируется, хотя конечный результат остается тем же: фильтрацию необходимо выполнять в JOIN, а не в результате JOIN.

Ответы [ 3 ]

4 голосов
/ 26 мая 2010

Это неправильно:

WHERE Year='1997'

Вам нужны строки, где Year равен 1997 или равен NULL, но NULL отфильтровываются из-за этого предложения WHERE. Используйте это вместо:

LEFT JOIN TableA AS a
ON p.Period = a.Period
AND Year = '1997'

Обратите внимание, что вам не нужно сохранять таблицу Periods. Вы также можете генерировать его динамически, используя рекурсивный CTE . Ваш рекурсивный CTE должен выглядеть так:

WITH Periods (Period) AS
(
    SELECT 1
    UNION ALL
    SELECT Period + 1 FROM Periods WHERE Period < 12
)
SELECT * FROM Periods
2 голосов
/ 26 мая 2010

Я думаю, что вам нужно LEFT OUTER JOIN

0 голосов
/ 26 мая 2010

Я думаю, что вы ищете

FULL OUTER JOIN
, потому что для каждого NULL "Года" соответствующее значение "TotalValue" также равно NULL!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...