2016-09-14 60 views
0

分組行我有問題的設備表記錄日期,如:SQL類型和ID

CREATE TABLE myTable 
    (`device_id` int, `datetime` datetime, `action` varchar(3)) 
; 

INSERT INTO myTable 
    (`device_id`, `datetime`, `action`) 
VALUES 
    (1, '2015-08-01 11:00', 'out'), 
    (1, '2015-08-01 11:05', 'out'), 
    (1, '2015-08-01 11:10', 'out'), 
    (1, '2015-08-01 11:15', 'out'), 
    (1, '2015-08-01 11:20', 'out'), 
    (2, '2015-08-01 11:25', 'out'), 
    (3, '2015-08-01 11:22', 'out'), 
    (4, '2015-08-01 11:45', 'out'), 
    (1, '2015-08-01 12:00', 'in'), 
    (1, '2015-08-01 12:01', 'in'), 
    (1, '2015-08-01 12:02', 'in'), 
    (1, '2015-08-01 12:03', 'in'), 
    (1, '2015-08-01 12:04', 'in'), 
    (1, '2015-08-01 12:05', 'in'), 
    (1, '2015-08-01 12:10', 'out'), 
    (2, '2015-08-01 12:12', 'in'), 
    (3, '2015-08-01 12:12', 'in'), 
    (3, '2015-08-01 12:22', 'out'), 
    (4, '2015-08-01 12:23', 'in'), 
    (1, '2015-08-01 08:00', 'in'), 
    (3, '2015-08-01 09:12', 'in') 
; 

查看sqlfiddle

例如如何分組的「出」和行「在「設備到一排?像:

datetime_out | datetime_in | device_id | 
-----------------+------------------+-----------+ 
2015-08-01 11:00 | 2015-08-01 12:05 | 1  | 
2015-08-01 11:25 | 2015-08-01 12:12 | 2  | 
2015-08-01 11:22 | 2015-08-01 12:12 | 3  | 
2015-08-01 11:45 | 2015-08-01 12:23 | 4  | 
2015-08-01 12:10 | 2015-09-03 08:00 | 1  | 
2015-08-01 12:22 | 2015-09-03 09:12 | 3  | 

UPD:

任何實例,數據庫管理系統並不重要。

如果我有多個「out」或行「中的」與序列相同DEVICE_ID隨後選擇行,最大的日期時間「在」用於和分鐘的日期時間爲「出」,例如:

datetime  | device_id | action | 
-----------------+-----------+--------+ 
2015-08-01 11:00 |  1  | out | <- Out 1 device 
2015-08-01 11:05 |  1  | out | <- ignore 
2015-08-01 11:10 |  1  | out | <- ignore 
2015-08-01 11:15 |  1  | out | <- ignore 
2015-08-01 11:20 |  1  | out | <- ignore 
2015-08-01 11:25 |  2  | out | 
2015-08-01 11:22 |  3  | out | 
2015-08-01 11:45 |  4  | out | 
2015-08-01 12:00 |  1  | in | <- ignore 
2015-08-01 12:01 |  1  | in | <- ignore 
2015-08-01 12:02 |  1  | in | <- ignore 
2015-08-01 12:03 |  1  | in | <- ignore 
2015-08-01 12:04 |  1  | in | <- ignore 
2015-08-01 12:05 |  1  | in | <- In 1 device 
2015-08-01 12:10 |  1  | out | <- Out 1 device 
2015-08-01 12:12 |  2  | in | 
2015-08-01 12:12 |  3  | in | 
2015-08-01 12:22 |  3  | out | 
2015-08-01 12:23 |  4  | in | 
2015-08-03 08:00 |  1  | in | <- In 1 device 
2015-08-03 09:12 |  3  | in | 
+1

你怎麼知道行是否匹配?如果在外出前有多個輸入,反之亦然? –

+1

我可以猜測,對於每一個,你都希望按照datetime順序排列下一個,但是你真的應該在你的問題中澄清一下。 – nycdan

+1

你正在使用哪些DBMS? –

回答

1

我會使用遊標來實現這一點。如果你沒有太多的行,並且不需要即時的結果,它可以很好。如果不是,我會定期在表格中填寫結果,或在某處保留「上次更新日期」,以便僅使用新信息更新表格。

見這裏的例子:http://rextester.com/JRW52552

下面是它可能是什麼樣子:

CREATE TABLE #Results (
    device_id INT, 
    datetime_out DATETIME, 
    datetime_in DATETIME 
) 

DECLARE device_cursor CURSOR FOR 
    SELECT DISTINCT device_id 
    FROM myTable 

DECLARE @device_id INT 
OPEN device_cursor 

FETCH NEXT FROM device_cursor INTO @device_id 
WHILE @@FETCH_STATUS = 0 
BEGIN 

    DECLARE @DeviceLastInDatetime DATETIME = '1901-01-01' 

    WHILE 1=1 --infinit loop to go through all out/in combinations 
    BEGIN 

     DECLARE @FirstOut DATETIME --find first out time after @DeviceLastInDatetime 
     SELECT @FirstOut = MIN(datetime) 
     FROM myTable 
     WHERE device_id = @device_id AND action = 'out' AND datetime > @DeviceLastInDatetime 
     PRINT '@FirstOut ' + CONVERT(VARCHAR, @FirstOut) --DEBUG 

     IF @FirstOut IS NULL --if no further out found, break infinit loop 
     BEGIN 
      BREAK 
     END 

     DECLARE @NextIn DATETIME --Find @NextIn --to go pass all next out datetime 
     SELECT @NextIn = MIN(datetime) 
     FROM myTable 
     WHERE device_id = @device_id AND action = 'in' AND datetime > @FirstOut 
     PRINT '@NextIn ' + CONVERT(VARCHAR, @NextIn) --DEBUG 

     DECLARE @NextOutAfterNextIn DATETIME --Find @NextOutAfterNextIn --to go pass all next in datetime 
     SELECT @NextOutAfterNextIn = ISNULL(MIN(datetime) , '2099-01-01') 
     FROM myTable 
     WHERE device_id = @device_id AND action = 'out' AND datetime > @NextIn 
     PRINT '@NextOutAfterNextIn ' + CONVERT(VARCHAR, @NextOutAfterNextIn) --DEBUG 

     DECLARE @FinalInDate DATETIME --last first 'in' before @NextOutAfterNextIn 
     SELECT @FinalInDate = MAX(datetime) 
     FROM myTable 
     WHERE device_id = @device_id AND action = 'in' AND datetime < @NextOutAfterNextIn 
     PRINT '@FinalInDate ' + CONVERT(VARCHAR, @FinalInDate) --DEBUG 

     INSERT INTO #Results VALUES (@device_id, @FirstOut, @FinalInDate) 

     SET @DeviceLastInDatetime = ISNULL(@FinalInDate, '2099-01-01') 
    END 


    --fetch next device 
    FETCH NEXT FROM device_cursor INTO @device_id 
END --device_cursor 


CLOSE device_cursor; 
DEALLOCATE device_cursor; 

SELECT * 
FROM #Results 
ORDER BY device_id, datetime_out 

DROP TABLE #Results 
+0

請檢查我的更新 – uralbash

+0

所以你想每個設備只有一行?在這種情況下,您的輸出示例將不正確,對嗎? –

+0

不完全一樣,每個設備都可以發佈並且可以進行多次。 您的查詢示例的工作原理與 幾乎相同,但「in」行必須按順序排列,最後在下一個已發佈(「in」)行之前選擇「out」。 不應顯示「in」行之前的下一個「out」行。在所示的例子中是正確的。 – uralbash