SQL Server CASE возвращает NULL, даже если есть значения

Ниже приведен пример моего запроса. Когда я запускаю запрос, PreviousTotalQuantity возвращает значение null, даже если в диапазоне дат есть данные.

SELECT
    p.ActualId,
    p.Name,
    p.QTYONHAND AS OnHand,
    p.PRICE AS DistCost,
    SUM(soi.Quantity) AS PresentTotal,
    SUM(CASE
        WHEN soi.MASSCHDSHIPDATE > '2014-3-1' AND
            soi.MASSCHDSHIPDATE < '2014-6-1' THEN soi.Quantity
        ELSE NULL
    END) AS PreviousTotalQuantity
FROM 
    sysdba.PRODUCT p
    LEFT OUTER JOIN sysdba.SALESORDERITEMS soi
        ON p.PRODUCTID = soi.PRODUCTID
WHERE 
    soi.MASSCHDSHIPDATE > '2015-3-1' AND 
    soi.MASSCHDSHIPDATE < '2015-6-1'
GROUP BY p.PRODUCTID, p.ACTUALID, p.NAME, p.QTYONHAND, p.PRICE

Мне также нужно получить данные за предыдущий год с заданной датой.


person Rom    schedule 02.10.2015    source источник
comment
Формат даты, который вы используете, может вызвать проблемы в зависимости от языковых настроек, вы всегда должны использовать ГГГГММДД.   -  person James Z    schedule 02.10.2015
comment
У вас есть таблица SALESORDERITEMS во внешнем соединении, но, поскольку вы используете ее в предложении where, она не будет внешне соединена. Переместите диапазон дат во внешнее соединение, если вам нужно внешнее соединение, но все же, если вы получаете только 2015 год, вы не получите 2014 год в случае   -  person James Z    schedule 02.10.2015


Ответы (3)


Потому что ваши годы не синхронизированы в части select (2014) и where (2015)

Изменить

SELECT
    p.ActualId,
    p.Name,
    p.QTYONHAND AS OnHand,
    p.PRICE AS DistCost,
    SUM(soi.Quantity) AS PresentTotal,
    ISNULL(prev.TotalQty, 0) AS PreviousTotalQuantity
FROM 
    sysdba.PRODUCT p
    LEFT OUTER JOIN sysdba.SALESORDERITEMS soi
        ON p.PRODUCTID = soi.PRODUCTID
    OUTER APPLY
    (
        SELECT SUM(Quantity) AS TotalQty 
        FROM sysdba.SALESORDERITEMS 
        WHERE PRODUCTID = p.PRODUCTID 
            AND MASSCHDSHIPDATE > '2014-03-01' AND MASSCHDSHIPDATE < '2014-06-01'
    ) AS prev
WHERE 
    soi.MASSCHDSHIPDATE > '2015-03-01' AND 
    soi.MASSCHDSHIPDATE < '2015-06-01'
GROUP BY p.PRODUCTID, p.ACTUALID, p.NAME, p.QTYONHAND, p.PRICE, prev.TotalQty
person Eric    schedule 02.10.2015
comment
Есть ли способ получить данные за те годы? Мне нужно получить данные за предыдущий год. - person Rom; 02.10.2015
comment
Это не проблема case, но данные, которые вы отфильтровали, относятся к текущему году, результат всегда будет нулевым или 0 (если вы исправите это как ответ Темного рыцаря). Исправьте свой запрос, используя подзапрос, чтобы выбрать предыдущий год - person Eric; 02.10.2015
comment
Привет, Эрик, я попробовал ваш запрос, но по какой-то причине он не отображает данные. Он выполняется слишком долго. - person Rom; 02.10.2015

Не сравнивайте дату вручную.

Используйте предложение between либо

Declare @PRODUCT table
(
Name varchar(50),
Date datetime,
Quantity int
)

INSERT INTO @PRODUCT VALUES ('Nikunj','2014-3-1',20)
INSERT INTO @PRODUCT VALUES ('Nikunj','2014-6-1',40)
INSERT INTO @PRODUCT VALUES ('Nikunj','2014-9-1',60)
INSERT INTO @PRODUCT VALUES ('JayDeep','2014-3-1',10)
INSERT INTO @PRODUCT VALUES ('JayDeep','2014-9-1',20)

select Name, sum(Quantity),SUM(Case when Date between '2014-3-1' and '2014-6-1' then Quantity else NULL end) TotalQuantity from @PRODUCT 
where Date between '2014-3-1' and '2014-6-1' group by Name 

Попробуйте это соответственно и проверьте year в коде условия where.

person Nikunj Soni    schedule 02.10.2015
comment
На самом деле в вашем условии вы упомянули 2015 год и пытаетесь найти данные за 2014 год. Вот почему вы не получаете никаких данных. - person Nikunj Soni; 02.10.2015
comment
попробуйте заменить это условие WHERE soi.MASSCHDSHIPDATE › '2014-3-1' AND soi.MASSCHDSHIPDATE ‹ '2014-6-1' в вашем коде - person Nikunj Soni; 02.10.2015
comment
то, что я пытаюсь сделать, это сравнить предыдущее и настоящее количество с заданной датой. Спасибо - person Rom; 02.10.2015

Проблема здесь в том, что вы ограничиваете строки в операторе WHERE 2015 годом, и из-за этого в результирующем наборе нет строк в 2014 году. Таким образом, вы получаете NULL, потому что CASE работает ПОСЛЕ оператора WHERE.

Если вам нужно выбрать текущий 2015 год и подсчитать это поле для 2014 года, вы можете использовать этот запрос. Я не знаю, уникален ли PRODUCTID в sysdba.PRODUCT, поэтому я использую подзапрос с DISTINCT. Если эти поля уникальны в PRODUCTS, просто используйте FROM PRODUCTS P без подзапроса DISTINCT:

SELECT
    p.ActualId,
    p.Name,
    p.QTYONHAND AS OnHand,
    p.PRICE AS DistCost,
    soi2015.SUM_Quantity AS PresentTotal,
    soi2014.SUM_Quantity AS PreviousTotalQuantity
FROM 
    (SELECT  DISTINCT 
             p.ActualId,
             p.Name,
             p.QTYONHAND AS OnHand,
             p.PRICE AS DistCost,        
             FROM sysdba.PRODUCT 
    ) p 
    LEFT OUTER JOIN 
      (SELECT PRODUCTID,SUM(soi.Quantity)  SUM_Quantity
        FROM  sysdba.SALESORDERITEMS
        WHERE (MASSCHDSHIPDATE > '2015-03-01') 
               AND (MASSCHDSHIPDATE < '2015-06-1')
        GROUP BY PRODUCTID
      ) soi2015 ON (p.PRODUCTID = soi2015.PRODUCTID) 
    LEFT OUTER JOIN 
      (SELECT PRODUCTID,SUM(soi.Quantity)  SUM_Quantity
        FROM  sysdba.SALESORDERITEMS
        WHERE (MASSCHDSHIPDATE > '2014-03-01') 
               AND (MASSCHDSHIPDATE < '2014-06-1')
        GROUP BY PRODUCTID
      ) soi2014 ON (p.PRODUCTID = soi2014.PRODUCTID) 
person valex    schedule 02.10.2015