我有一个发布设备的表记录日期,如:
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
上的示例如何分组" out"和" in"设备到一排?像:
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:
任何例子,DBMS都不重要。
如果我有多个" out"或" in"依次具有相同device_id的行然后选择具有最大日期时间的行"在"和#34; out"的最小日期时间,例如:
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 |
答案 0 :(得分:1)
我会使用游标来实现这一目标。如果你没有太多行并且不需要即时结果,那就没问题了。如果不是,我会定期填写表格,或者保留一个&#34;最后更新日期&#34;某处只使用新信息更新表格。
请参阅此处的示例: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