简体   繁体   中英

Using SQL Server 2012 LAG

I am trying to write a query using SQL Server 2012 LAG function to retrieve data from my [Order] table where the datetime difference between a row and the previous row is less than equal to 2 minutes.

The result I'm expecting is

1234    April, 28 2012 09:00:00

1234    April, 28 2012 09:01:00

1234    April, 28 2012 09:03:00

5678    April, 28 2012 09:40:00

5678    April, 28 2012 09:42:00

5678    April, 28 2012 09:44:00

but I'm seeing

1234    April, 28 2012 09:00:00

1234    April, 28 2012 09:01:00

1234    April, 28 2012 09:03:00

5678    April, 28 2012 09:40:00

5678    April, 28 2012 09:42:00

5678    April, 28 2012 09:44:00

91011   April, 28 2012 10:00:00

The last row should not be returned. Here is what I have tried: SQL Fiddle

Any one with ideas?

Okay first of all I added a row to show you where someone else's answer doesn't work but they deleted it now.

Now for the logic in my query. You said you want each row that is within two minutes of another row. That means you have to look not only backwards, but also forwards with LEAD(). In your query, you returned when previous time was NULL so it simply returned the first value of each OrderNumber regardless if it was right or wrong. By chance, the first values of each of your OrderNumbers needed to be returned until you get to the last OrderNumber where it broke. My query corrects that and should work for all your data.

CREATE TABLE [Order]  
    (
            OrderNumber    VARCHAR(20) NOT NULL
        ,   OrderDateTime   DATETIME NOT NULL
    );

    INSERT [Order] (OrderNumber, OrderDateTime) 
    VALUES
        ('1234', '2012-04-28 09:00:00'),
        ('1234', '2012-04-28 09:01:00'),
        ('1234', '2012-04-28 09:03:00'),
        ('5678', '2012-04-28 09:40:00'),
        ('5678', '2012-04-28 09:42:00'),
        ('5678', '2012-04-28 09:44:00'),
        ('91011', '2012-04-28 10:00:00'),
        ('91011', '2012-04-28 10:25:00'),
        ('91011', '2012-04-28 10:27:00');

with Ordered as (
  select
    OrderNumber,
    OrderDateTime,
    LAG(OrderDateTime,1) over (
      partition by OrderNumber
      order by OrderDateTime
    ) as prev_time,
    LEAD(OrderDateTime,1) over (
      partition by OrderNumber
      order by OrderDateTime
    ) as next_time
  from [Order]
)

SELECT  OrderNumber,
        OrderDateTime
FROM Ordered
WHERE   DATEDIFF(MINUTE,OrderDateTime,next_time) <= 2  --this says if the next value is less than or equal to two minutes away return it
        OR DATEDIFF(MINUTE,prev_time,OrderDateTime) <= 2 --this says if the prev value is less than or equal to 2 minutes away return it

Results(Remember I added a row):

OrderNumber          OrderDateTime
-------------------- -----------------------
1234                 2012-04-28 09:00:00.000
1234                 2012-04-28 09:01:00.000
1234                 2012-04-28 09:03:00.000
5678                 2012-04-28 09:40:00.000
5678                 2012-04-28 09:42:00.000
5678                 2012-04-28 09:44:00.000
91011                2012-04-28 10:25:00.000
91011                2012-04-28 10:27:00.000

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM