SQL полное соединение с Где - PullRequest
1 голос
/ 09 ноября 2011

Я пытаюсь объединить две таблицы в SQL, одна из которых содержит список товаров, а другая - даты, когда они были проданы. Я получил часть соединения, но мне нужно получить информацию из таблицы REPORT, но все элементы таблицы VENDORS. Мне нужно, чтобы товары, которые не были проданы, отображались как NULL или, предпочтительно, 0. Это код, который я использую до сих пор, и он показывает только товары, которые были проданы в данный день.

SELECT t2.[DATE]
      ,t1.[VENDOR]
      ,t1.[UPC]
      ,t2.[QTY]
      ,t2.[AMOUNT]
FROM [STORESQL].[dbo].[VENDORS] t1
LEFT OUTER JOIN [STORESQL].[dbo].[REPORT] t2 ON t1.UPC=t2.UPC
WHERE VENDOR='119828' AND DATE='2011-11-8'

и примеры таблиц:

ПРОДАВЦЫ:

VENDOR   UPC
119828   1
119828   2
119828   3

ОТЧЕТ:

* * 1010

Текущий код приводит к

DATE       VENDOR    UPC    QTY    AMOUNT
2011-11-8  119828    1      1      9.99
2011-11-8  119828    3      2      18.98

Мне нужно, чтобы показать

DATE       VENDOR    UPC    QTY    AMOUNT
2011-11-8  119828    1      1      9.99
2011-11-8  119828    2      0      0.00
2011-11-8  119828    3      2      18.98

Я знаю, что делаю что-то не так, но я не знаю, что это такое. Заранее спасибо.

Ответы [ 3 ]

5 голосов
/ 09 ноября 2011

Попробуйте вместо этого:

SELECT t2.[DATE]
      ,t1.[VENDOR]
      ,t1.[UPC]
      ,t2.[QTY]
      ,t2.[AMOUNT]
FROM [STORESQL].[dbo].[VENDORS] t1
LEFT OUTER JOIN [STORESQL].[dbo].[REPORT] t2 ON t1.UPC=t2.UPC AND DATE='2011-11-8'
WHERE VENDOR='119828'

Предложение where для DATE делает ваше внешнее соединение функционирующим как внутреннее соединение, потому что сравнение будет с нулевым значением в DATE.Перемещение сравнения в предложение ON должно с этим справиться.

Чтобы в результате получить 0 вместо нуля, вы можете использовать COALESCE:

,COALESCE(t2.[QTY], 0)
,COALESCE(t2.[AMOUNT], 0)

Ваш столбец даты также будет нулевымэто также можно исправить с помощью COALESCE:

COALESCE(t2.[DATE], '2011-11-8')
1 голос
/ 09 ноября 2011

Это несовместимо:

  • WHERE t2.DATE='2011-11-8'
  • Мне нужно, чтобы предметы, которые не были проданы, отображались как NULL .

Первое предложение WHERE отменяет все эффекты OUTER JOIN, потому что вы удаляете все записи, для которых не найдено совпадений для вашей строки в T1. Может быть, вы хотите:

WHERE VENDOR='119828' AND (DATE='2011-11-8' OR DATE IS NULL)
0 голосов
/ 09 ноября 2011
WITH VENDORS
     AS 
     (
      SELECT * 
        FROM (
              VALUES (119828, 1),
                     (119828, 2), 
                     (119828, 3)
             ) AS T (VENDOR, UPC)
     ),
     REPORT
     AS 
     (
      SELECT * 
        FROM (
              VALUES ('2011-11-08T00:00:00', 1, 1, 9.99), 
                     ('2011-11-08T00:00:00', 3, 2, 18.98)
             ) AS T ("DATE", UPC, QTY, AMOUNT)
     ), 
     AllReportDates
     AS
     (
      SELECT DISTINCT "DATE" 
        FROM REPORT
     )
SELECT r."DATE", v.VENDOR, v.UPC, r.QTY, r.AMOUNT
  FROM VENDORS v
       JOIN REPORT r
          ON v.UPC = r.UPC
UNION
SELECT a."DATE", v.VENDOR, v.UPC, 0 AS QTY, 0.00 AS AMOUNT
  FROM VENDORS v
       CROSS JOIN AllReportDates a
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM REPORT r
                    WHERE r.UPC = v.UPC
                          AND r."DATE" = a."DATE"
                  );
...