sql - MsSQL LEFT JOIN 与双 GROUP BY
问题描述
我目前正在尝试将 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 为 null,但是,如果 count 为 null,则不会显示每个 Destination。如下图所示:
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 来解决这个问题,但没有运气。
解决方案
我建议创建一个数字表或日历表,但递归查询对于小型集合就足够了。
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
推荐阅读
- javascript - 如何刷新日历中的事件日期(日期选择器)
- python - 查找输入是否在列表中
- javascript - 如何从base64音频数据中获取元数据
- vhdl - 如何修复位置关联错误 (10437)
- gora - $bin/gora 文件没有运行它总是在 cmd 中说“它不被识别为内部或外部命令”
- .htaccess - 使用 GET 参数重写 URL
- openmp - 找不到 OpenMP 环境变量
- python - 有没有更快的方法来使用 PIL 在图像中查找像素(按颜色)
- javascript - Javascript多维数组长度问题
- python - 'AssertionError:Torch 未在启用 CUDA 的情况下编译'