所以我的任务是查找每个订单的延迟时间(以周为单位)。我使用过DATEDIFF
函数,但我想我走在正确的轨道上,但是当我使用它时,得到的结果就是NULL
。每列的数据类型均为日期。
SELECT DISTINCT Sales.Orders.custid, Sales.Customers.companyname,
CASE
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) = 7 AND DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 14 THEN '1 Week'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) = 14 AND DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 21 THEN '2 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) = 21 AND DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 28 THEN '3 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) = 28 AND DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 35 THEN '4 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) = 35 AND DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 42 THEN '5 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) = 42 AND DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 49 THEN '6 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) > 49 THEN '7+ Weeks'
ELSE 'Unknown'
END AS Order_Delay
FROM Sales.Orders, Sales.Customers
ORDER BY
Order_Delay ASC;
我正在使用MS SQL Server Management Studio 2016。
答案 0 :(得分:2)
FROM Sales.Orders, Sales.Customers
是形成cross join
的老式方法。这可能是偶然的,但是这样做对性能的影响可能是可怕的,但结果可能是完全错误的-在您的示例中。因此,我始终建议您使用显式联接语法(例如inner join
和使用逗号停止作为定义from子句的方式。
您只需要正确地连接2个表,否则每个订单都将应用到每个客户,结果将是非常错误的。我猜想该联接,但是它看起来应该类似于下面看到的联接:
SELECT /* DISTINCT ?? */
Sales.Orders.custid
, Sales.Customers.companyname
, CASE
WHEN ca.Order_Delay >= 7 THEN '7+ Weeks'
WHEN ca.Order_Delay >= 1 AND ca.Order_Delay < 7 THEN CAST(ca.Order_Delay AS varchar) + ' Weeks'
ELSE 'Unknown'
END AS order_delay
FROM Sales.Orders AS o
INNER JOIN Sales.Customers AS c ON o.custid = c.id
CROSS APPLY (
SELECT
FLOOR(DATEDIFF(DAY, o.shippeddate, o.orderdate) / 7)
) ca (order_delay)
ORDER BY
order_delay ASC
;
在SQL Server中,可以使用cross apply
作为执行计算的方式,并为该计算提供一个别名,然后可以在select子句中使用它。这样可以使您的代码更易于阅读,但这是可选的。
以上,我建议了一种使用floor()
的方法,您应该在此处阅读以下内容:
https://docs.microsoft.com/en-us/sql/t-sql/functions/floor-transact-sql?view=sql-server-2017
nb:如果要显示未发货订单的数据,则可能需要更改为outer apply
,如果未发货订单,则datediff()
函数将返回NULL,而您的{{1 }}需要显式地满足NULL
case expression
答案 1 :(得分:1)
尝试像这样重写查询:
SELECT DISTINCT Sales.Orders.custid, Sales.Customers.companyname,
CASE
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) >= 7 AND DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 14 THEN '1 Week'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 21 THEN '2 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 28 THEN '3 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 35 THEN '4 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 42 THEN '5 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 49 THEN '6 Weeks'
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) >= 49 THEN '7+ Weeks'
ELSE 'Unknown'
END AS Order_Delay
FROM Sales.Orders, Sales.Customers
ORDER BY
Order_Delay ASC;
我认为您想检查差异是否在特定范围内(从7到14,等等)。
所以我更正了第一个条件:
WHEN DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) >= 7 AND DATEDIFF(DAY, Sales.Orders.shippeddate, Sales.Orders.orderdate) < 14 THEN '1 Week'
您不能在此处使用BETWEEN
,因为它的范围还包括一组的兄弟。
对于其他情况,您无需检查差异是否大于例如。在第二WHEN
中,您知道差异为>=14
,因为它在第一个条件下失败,等等。
答案 2 :(得分:1)
https://docs.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-2017
DATEDIFF(datepart,startdate,enddate)
我的猜测是,您系统中的shippeddate
主要是以后或等于orderdate
,因此不是
FLOOR(DATEDIFF(DAY, o.shippeddate, o.orderdate) / 7)
您可能想要
FLOOR(DATEDIFF(DAY, o.orderdate, o.shippeddate) / 7)
要检查此假设,您可能想将ca.Order_Delay
(按照@Used_by_already建议的代码)添加到所选列的列表中,并查看其中有什么值。我敢打赌,他们都是负面的。
答案 3 :(得分:0)
您要查找的恰好是7、14、21等。您需要> = 7(然后重复其余步骤...)。