MsSQL LEFT JOIN с двойным GROUP BY - PullRequest
0 голосов
/ 04 октября 2018

Я сейчас пытаюсь использовать MsSQL для БД доставки товара.Я потратил много времени, пытаясь написать запрос SQL, чтобы получить количество продуктов, поступающих в каждое место доставки в области, за дату, за 4-дневный период, начинающийся сегодня.Под областью подразумевается, что есть другое местоположение, которое является родительским для этого местоположения.

Соответствующие таблицы являются продуктами и местоположениями и структурированы следующим образом

Products    
ProductID  DeliveryDate  DestinationID
1          2018-10-05    1
2          2018-10-05    2
3          2018-10-05    3
4          2018-10-06    1
5          2018-10-06    5

Locations
LocationID  OwnerID     
1           4
2           4
3           4
4           Null
5           6
6           Null

Требуемый результат выглядит следующим образом

DeliveryDate  Destination ProductCount
2018-10-04    1           Null
2018-10-04    2           Null
2018-10-04    3           Null
2018-10-05    1           1
2018-10-05    2           1
2018-10-05    3           1 
2018-10-06    1           1
2018-10-06    2           Null
2018-10-06    3           Null
2018-10-07    1           Null
2018-10-07    2           Null
2018-10-07    3           Null

То, что я до сих пор пробовал, это

DECLARE @startdate DATETIME
    ,@enddate DATETIME

SET @startdate = convert(varchar, '2018-10-04 00:00:00', 102)
SET @enddate = convert(varchar, '2018-10-07 00:00:00', 102)

;WITH DateArray
AS (
    SELECT @startdate DateVal

    UNION ALL

    SELECT DateVal + 1
    FROM DateArray
    WHERE DateVal + 1 <= @enddate
    )
SELECT * FROM
(SELECT da.DateVal AS DeliveryDate
FROM DateArray da) a
LEFT JOIN 
(SELECT ISNULL(COUNT(p.ProductID),0) AS ProductCount,
        DeliveryDate,
        ISNULL(p.DestinationID,'') AS Destination
FROM Product p
AND p.DestinationID IN(SELECT LocationID FROM Locations WHERE OwnerID = 4)
GROUP BY p.DestinationID, p.DeliveryDate) AS b
ON b.DeliveryDate = a.DeliveryDate

Результат гарантирует, что присутствуют все даты, даже если ProductCount равен нулю, однако не все пункты назначения отображаются, если счетчик равенноль.Показанный ниже.

DeliveryDate  Destination  ProductCount
2018-10-04    Null        Null
2018-10-05    1           1
2018-10-05    2           1
2018-10-05    3           1 
2018-10-06    1           1
2018-10-07    Null        Null

Я провел два дня упорно пытается понять это со многими интернет-ресурсов SQL и чистящими StackOverflow, но не повезло

1 Ответ

0 голосов
/ 04 октября 2018

Я рекомендую создать таблицу чисел или таблицу календаря, но для небольших наборов достаточно рекурсивного запроса.

DECLARE
  @startdate DATETIME = '2018-10-04 00:00:00',
  @enddate   DATETIME = '2018-10-07 00:00:00';

WITH
  DateArray AS
(
  SELECT @startdate DateVal
  UNION ALL
  SELECT DateVal + 1 FROM DateArray WHERE DateVal + 1 <= @enddate
)
SELECT
  DateArray.DateVal          AS DeliveryDate,
  Locations.LocationID       AS Destination,
  COUNT(Products.ProductID)  AS ProductCount
FROM
  DateArray
CROSS JOIN
(
  SELECT * FROM Locations WHERE OwnerID = 4
)
  Locations
LEFT JOIN
  Products
    ON  Products.DeliveryDate  = DateArray.DateVal
    AND Products.DestinationID = Locations.LocationID
GROUP BY
  DateArray.DateVal,
  Locations.LocationID

Или ...

SELECT
  DateArray.DateVal          AS DeliveryDate,
  Locations.LocationID       AS Destination,
  Products.ProductCount      AS ProductCount
FROM
  DateArray
CROSS JOIN
(
  SELECT * FROM Locations WHERE OwnerID = 4
)
  Locations
LEFT JOIN
(
  SELECT DeliveryDate, DestinationID, COUNT(*) AS ProductCount
    FROM Products
GROUP BY DeliveryDate, DestinationID
)
  Products
    ON  Products.DeliveryDate  = DateArray.DateVal
    AND Products.DestinationID = Locations.LocationID
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...