如何通过 table 循环查找数据集?

how to loop thru a table to find data set?

我必须找到订单生命周期的时差(以分钟为单位)。 即每个订单从收到订单(Activity ID 1)到输入(2)到打印(3)到交付(4)的时间

例如

我完全不知道我应该采用哪种方法?? 用例或 if then 语句 ??每个循环遍历每条记录之类的东西? 最有效的方法应该是什么?

我知道一旦我在正确的变量中获得日期,我就可以使用 DATEDIFF。

declare @received as Datetime, @keyed as DateTime, @printed as Datetime, @Delivered as Datetime, @TurnTime1 as int
Select
IF (tblOrderActivity.ActivityID = 1) SET @received = tblOrderActivity.ActivityDate
---
----
from tblOrderActivity
where OrderID = 1 

它应该告诉我@TurnTime1 = 48 分钟,因为 orderID 1 从收到(activity id 1)到键入(activity id 2)需要 48 分钟@TurnTime2 = 29 分钟订单 1 从键控(activity id 2)到打印(activity id 3)需要 29 分钟,依此类推每个订单

正如您在问题中提到的,一种可能的方法是使用 CASE 语句

DECLARE @i INT, @max INT
SELECT @i = MIN(OrderId) FROM tblOrderActivity
SELECT @max = MAX(OrderId) from tblOrderActivity

WHILE @i <= @max
BEGIN
SELECT OrderId
       ,ActivityID
       ,ActivityDate
       ,CASE
        WHEN ActivityID = 1 THEN DATEDIFF(MINUTE, ActivityDate, (SELECT ActivityDate FROM C WHERE ActivityID = 2 AND OrderId = @i))
        END AS tokeyed
       ,CASE
        WHEN ActivityID = 2 THEN DATEDIFF(MINUTE, ActivityDate, (SELECT ActivityDate FROM C WHERE ActivityID = 3 AND OrderId = @i))
        END AS toprinted
       ,CASE
        WHEN ActivityID = 3 THEN DATEDIFF(MINUTE, ActivityDate, (SELECT ActivityDate FROM C WHERE ActivityID = 4 AND OrderId = @i))
        END AS todelivered
FROM tblOrderActivity

SET @i = @i + 1
END

这个应该可以满足您的需求,但我建议您在将值插入 table 并直接将此值添加到新列中时使用此查询

SELECT OrderID,
       ActivityID,
       ActivityDate,
       Datediff(MINUTE, ActivityDate, (SELECT ActivityDate
                                       FROM   [TestDB].[dbo].[tblOrderActivity] AS b
                                       WHERE  b.OrderID = a.OrderID
                                              AND a.ActivityID + 1 = b.ActivityID))
FROM   [TestDB].[dbo].[tblOrderActivity] AS a 

首先我列出了所有订单 (CTE_Orders)。

对于每个订单,我得到四个日期,每个 ActivityID 使用 OUTER APPLY。我假设某些活动可能会丢失(尚未完成),所以 OUTER APPLY 会 return NULL 在那里。当我计算持续时间时,我假设如果 activity 不在数据库中,它还没有发生,我计算持续时间到当前时间。如果您有其他需求,可以另行处理。

我假设每个订单最多只能有一行 Activity ID。如果您可以有两行或更多行具有相同的 Order IDActivity ID,那么您需要通过将 ORDER BY 添加到 SELECT 内的 [=] 来决定选择哪一行13=].

DECLARE @TOrders TABLE (OrderID int, ActivityID int, ActivityDate datetime);

INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (1, 1, '2007-04-16T08:34:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (1, 1, '2007-04-16T08:34:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (1, 2, '2007-04-16T09:22:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (1, 3, '2007-04-16T09:51:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (1, 4, '2007-04-16T16:14:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (2, 1, '2007-04-16T08:34:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (3, 1, '2007-04-16T08:34:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (3, 2, '2007-04-16T09:22:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (3, 3, '2007-04-16T09:51:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (3, 4, '2007-04-16T16:14:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (4, 1, '2007-04-16T08:34:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (4, 2, '2007-04-16T09:22:00');
INSERT INTO @TOrders (OrderID, ActivityID, ActivityDate) VALUES (4, 3, '2007-04-16T09:51:00');

WITH
CTE_Orders
AS
(
    SELECT DISTINCT Orders.OrderID
    FROM @TOrders AS Orders
)
SELECT
    CTE_Orders.OrderID
    ,Date1_Received
    ,Date2_Keyed
    ,Date3_Printed
    ,Date4_Delivered
    ,DATEDIFF(minute, ISNULL(Date1_Received, GETDATE()), ISNULL(Date2_Keyed, GETDATE())) AS Time12
    ,DATEDIFF(minute, ISNULL(Date2_Keyed, GETDATE()), ISNULL(Date3_Printed, GETDATE())) AS Time23
    ,DATEDIFF(minute, ISNULL(Date3_Printed, GETDATE()), ISNULL(Date4_Delivered, GETDATE())) AS Time34
FROM
    CTE_Orders
    OUTER APPLY
    (
        SELECT TOP(1) Orders.ActivityDate AS Date1_Received
        FROM @TOrders AS Orders
        WHERE
            Orders.OrderID = CTE_Orders.OrderID
            AND Orders.ActivityID = 1
    ) AS OA1_Received
    OUTER APPLY
    (
        SELECT TOP(1) Orders.ActivityDate AS Date2_Keyed
        FROM @TOrders AS Orders
        WHERE
            Orders.OrderID = CTE_Orders.OrderID
            AND Orders.ActivityID = 2
    ) AS OA2_Keyed
    OUTER APPLY
    (
        SELECT TOP(1) Orders.ActivityDate AS Date3_Printed
        FROM @TOrders AS Orders
        WHERE
            Orders.OrderID = CTE_Orders.OrderID
            AND Orders.ActivityID = 3
    ) AS OA3_Printed
    OUTER APPLY
    (
        SELECT TOP(1) Orders.ActivityDate AS Date4_Delivered
        FROM @TOrders AS Orders
        WHERE
            Orders.OrderID = CTE_Orders.OrderID
            AND Orders.ActivityID = 4
    ) AS OA4_Delivered
ORDER BY OrderID;

这是结果集:

OrderID    Date1_Received             Date2_Keyed                Date3_Printed              Date4_Delivered            Time12    Time23    Time34
1          2007-04-16 08:34:00.000    2007-04-16 09:22:00.000    2007-04-16 09:51:00.000    2007-04-16 16:14:00.000    48        29        383
2          2007-04-16 08:34:00.000    NULL                       NULL                       NULL                       4082575   0         0
3          2007-04-16 08:34:00.000    2007-04-16 09:22:00.000    2007-04-16 09:51:00.000    2007-04-16 16:14:00.000    48        29        383
4          2007-04-16 08:34:00.000    2007-04-16 09:22:00.000    2007-04-16 09:51:00.000    NULL                       48        29        4082498

您可以轻松计算其他持续时间,例如订单的总时间(时间 4 - 时间 1)。

一旦你有几个不同的查询产生了你需要的相同的正确结果,你应该用你系统上的真实数据来衡量它们的性能,以确定哪个更有效。

您可以通过 pivoting 轻松完成此操作 data.It 可以通过两种方式完成。

1.Use Conditional Aggregate 转置数据。在 pivoting 之后,您可以在不同阶段之间找到 datediff。试试这个。

SELECT orderid,Received,Keyed,Printed,Delivered,
       Datediff(minute, Received, Keyed)    TurnTime1,
       Datediff(minute, Keyed, Printed)     TurnTime2,
       Datediff(minute, Printed, Delivered) TurnTime3
FROM  (SELECT OrderID,
              Max(CASE WHEN ActivityID = 1 THEN ActivityDate END) Received,
              Max(CASE WHEN ActivityID = 2 THEN ActivityDate END) Keyed,
              Max(CASE WHEN ActivityID = 3 THEN ActivityDate END) Printed,
              Max(CASE WHEN ActivityID = 4 THEN ActivityDate END) Delivered
       FROM   Yourtable
       GROUP  BY OrderID)A 

2.use Pivot 转置数据

SELECT orderid,
       [1]                        AS Received,
       [2]                        AS Keyed,
       [3]                        AS Printed,
       [4]                        AS Delivered,
       Datediff(minute, [1], [2]) TurnTime1,
       Datediff(minute, [2], [3]) TurnTime2,
       Datediff(minute, [3], [4]) TurnTime3
FROM   Yourtable
       PIVOT (Max(ActivityDate)
             FOR ActivityID IN([1],[2],[3],[4]))piv