Прежде всего, есть некоторые проблемы с вашим запросом:
Ваш пункт SELECT
содержит столбец, который не является ни в GROUP BY
ни агрегируются - WM_qtd
. Вы имели в виду SUM(WM_qtd)
, не так ли?
В целом, даты, отформатированные с CONVERT(103)
, не могут быть осмысленно сопоставлены или отсортированы. Я бы посоветовал вам использовать другой формат (например, 112
) или использовать другой метод удаления временной части вообще и применить форматирование позже (только в предложении SELECT
или, возможно, вообще не в SQL).
Вы фильтруете исходный набор данных с помощью предложения HAVING
, что является неэффективным, поскольку все данные должны быть вытащены, сгруппированы и только затем отфильтрованы. В этом конкретном случае было бы лучше отфильтровать данные с помощью предложения WHERE
.
Теперь за ваш вопрос ... Результирующий набор вы после в основном кросс-произведение всех соответствующих дат и всех соответствующих продуктов (ой, простите за каламбур). Он просто содержит некоторую дополнительную информацию, например «Количество».
Таким образом, вам необходимо получить два списка, даты и продукты, перекрестия их, затем вы можете подключить внешний результирующий набор к Tb_InfoProduct
и группировать по дате и продукту, чтобы получить номера - то же, что вы уже делаете в вашем запросе будут указаны только столбцы даты и продукта, которые должны быть указаны в статьях GROUP BY
и SELECT
, в соответствующих производных списках, а не в таблице Tb_InfoProduct
.
Для моего ответа я предполагаю, что подмножество Tb_InfoProduct
, которое вы запрашиваете, содержит все даты и все продукты, которые должны присутствовать на выходе, поэтому для получения двух списков я просто выбор отдельных дат и отдельных продуктов из подмножества Tb_InfoProduct
. Вот приближенное решение в полном объеме:
SELECT
Date = CONVERT(VARCHAR(10), d.Date, 103),
Product = CASE p.WM_Product
WHEN 1 THEN 'Product A'
WHEN 2 THEN 'Product B'
ELSE 'Product C'
END,
Quantity = SUM(WM_qtd)
FROM (
SELECT DISTINCT Date = DATEADD(DAY, DATEDIFF(DAY, 0, WM_data), 0)
FROM Tb_InfoProduct
WHERE WM_data >= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 4, 0)
) d
CROSS JOIN (
SELECT DISTINCT WM_Product
FROM Tb_InfoProduct
WHERE WM_data >= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 4, 0)
) p
LEFT JOIN (
SELECT
Date = DATEADD(DAY, DATEDIFF(DAY, 0, WM_data), 0),
WM_Product
FROM Tb_InfoProduct
WHERE WM_data >= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 4, 0)
) i ON d.Date = i.Date AND p.WM_Product = i.WM_Product
GROUP BY
d.Date,
p.WM_Product
ORDER BY
d.Date,
p.WM_Product
Если запрашиваемое подмножество может пропустить некоторые даты и/или продукты, которые вы предпочли бы включить в выводе, вы должны создать список (ов) иначе. Например, вы можете использовать таблицу ссылок Products
для списка продуктов, если она у вас есть, конечно. Что касается дат, вам может понадобиться сгенерировать список дат для данного диапазона, как предложил @OMG Ponies (и этот вопрос мог бы помочь вам с этим: Get a list of dates between two dates using a function).
Вы должны иметь (или генерировать) список дат, которые вы затем OUTER присоединиться к на значении даты. –
Как в стороне, вы должны сделать фильтрацию в разделе 'WHERE' (используя объекты даты, а не строки) – Leigh