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

时间:2015-01-18 23:44:52

标签: sql sql-server sql-server-2008 tsql

我必须在几分钟内找到订单生命周期的timediff。 即从订单收到的时间(活动ID 1)到键盘(2)到打印(3)到交付(4)每个订单

例如

我完全迷失了应该采取哪种方法?  用例还是如果声明?通过每个记录循环的东西? 什么应该是最有效的方法呢?

我知道一旦我得到正确变量的日期,我就可以使用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从收到(活动ID 1)到键控(活动ID 2)需要48分钟@TurnTime2 = 29分钟,因为从键控(活动ID 2)开始需要29分钟的订单1 )为每个订单打印(活动ID 3)等等

4 个答案:

答案 0 :(得分:4)

您可以通过pivoting数据轻松完成此操作。可以通过两种方式完成。

1.使用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.使用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 

答案 1 :(得分:1)

正如您在问题中提到的,一种可能的方法是使用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

答案 2 :(得分:1)

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

对于每个订单,我得到四个日期,每个ActivityID使用OUTER APPLY一个。我假设某些活动可能会丢失(尚未完成),因此OUTER APPLY会返回NULL。当我计算持续时间时,我假设如果活动不在数据库中,它还没有发生,我计算持续时间直到当前时间。如果您有其他要求,可以采用不同的方式处理这种情况。

我假设每个订单每个Activity ID最多只能有一行。如果您有两行或多行具有相同的Order IDActivity ID,那么您需要通过将ORDER BY添加到SELECTOUTER APPLY来决定选择哪一行1}}。

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)。

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

答案 3 :(得分:0)

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

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