遍历 SQL 中的数据
Iterate over data in SQL
拥有此数据集:https://www.db-fiddle.com/f/6vmgx4krsgMRgprDjErdqu/0
我想有一个额外的列显示到之前条目的时间距离,我该如何实现?
非常感谢您:)
像这样的东西就可以了:
insert into @temp ([ID], [Date])
select
t.[ID],
datediff(day, Lag(t.[Date]) over(order by t.[Date]), t.[Date]) as [DateDiffFromPrevRow]
from someTable t
select
t.[ID],
t.[POS],
t.[Date],
t.[Customer],
temp.[DateDiffFromPrevRow]
from sometable t
join @temp temp on temp.[ID] = t.[ID]
正如您在 fiddle 中所述,您使用 MySQL 5,7
您必须使用用户定义的变量。
我选择了 TIMEDIFF 来显示差异,因为你没有说明你需要哪些信息,所以我选择了这个,但是因为你有两个值,你可以使用不同的 mysql 函数
架构(MySQL v5.7)
CREATE TABLE `someTable` (
`ID` INT,
`POS` INT,
`Date` DATETIME,
`Customer` VARCHAR(64)
);
INSERT INTO `someTable` VALUES
(1, 10, "2017-03-10 08:00:00", "Peter"),
(2, 11, "2017-03-10 08:00:01", "Peter"),
(3, 12, "2017-03-10 08:00:04", "Peter"),
(4, 17, "2017-03-10 08:00:05", "Peter"),
(5, 16, "2017-03-10 08:00:08", "Karl"),
(6, 17, "2017-03-10 08:00:09", "Karl"),
(7, 10, "2017-03-10 08:00:12", "Peter"),
(8, 10, "2017-03-10 08:00:13", "Peter");
SELECT * FROM someTable
查询#1
SELECT
ID,
POS
,`Customer`
,IF(@date = `Date`,0,TIMEDIFF(`Date`, @date)) diff
,@date := `Date` 'Date'
FROM someTable, (SELECT @date := (SELECT MIN(`Date`) FROM someTable)) A;
| ID | POS | Customer | diff | Date |
| --- | --- | -------- | --------------- | ------------------- |
| 1 | 10 | Peter | 0 | 2017-03-10 08:00:00 |
| 2 | 11 | Peter | 00:00:01.000000 | 2017-03-10 08:00:01 |
| 3 | 12 | Peter | 00:00:03.000000 | 2017-03-10 08:00:04 |
| 4 | 17 | Peter | 00:00:01.000000 | 2017-03-10 08:00:05 |
| 5 | 16 | Karl | 00:00:03.000000 | 2017-03-10 08:00:08 |
| 6 | 17 | Karl | 00:00:01.000000 | 2017-03-10 08:00:09 |
| 7 | 10 | Peter | 00:00:03.000000 | 2017-03-10 08:00:12 |
| 8 | 10 | Peter | 00:00:01.000000 | 2017-03-10 08:00:13 |
如果您是运行 MySQL 8.0,只需使用lag()
和timetstampdiff()
。假设你想要与相同customer
的“先前”记录的日期差异,并且应该以秒表示:
select
t.*,
timestampdiff(
second,
lag(date, 1, date) over(partition by customer order by date),
date
) diff_seconds
from sometable t
每组的第一条记录相差 0
秒。
如果你是运行更早的版本,那么我会推荐相关子查询。虽然它可能比用户变量效率低一点,但它更安全,并且future-proof(用户变量计划在MySQL的未来版本中删除):
select
t.*,
timestampdiff(
second,
coalesce((select max(t1.date) from sometable t1 where t1.customer = t.customer and t1.date < t.date), date),
date
) diff_seconds
from sometable t
对于您的样本数据,both queries return:
| ID | POS | Date | Customer | diff_seconds |
| --- | --- | ------------------- | -------- | ------------ |
| 1 | 10 | 2017-03-10 08:00:00 | Peter | 0 |
| 2 | 11 | 2017-03-10 08:00:01 | Peter | 1 |
| 3 | 12 | 2017-03-10 08:00:04 | Peter | 3 |
| 4 | 17 | 2017-03-10 08:00:05 | Peter | 1 |
| 5 | 16 | 2017-03-10 08:00:08 | Karl | 0 |
| 6 | 17 | 2017-03-10 08:00:09 | Karl | 1 |
| 7 | 10 | 2017-03-10 08:00:12 | Peter | 7 |
| 8 | 10 | 2017-03-10 08:00:13 | Peter | 1 |
拥有此数据集:https://www.db-fiddle.com/f/6vmgx4krsgMRgprDjErdqu/0
我想有一个额外的列显示到之前条目的时间距离,我该如何实现?
非常感谢您:)
像这样的东西就可以了:
insert into @temp ([ID], [Date])
select
t.[ID],
datediff(day, Lag(t.[Date]) over(order by t.[Date]), t.[Date]) as [DateDiffFromPrevRow]
from someTable t
select
t.[ID],
t.[POS],
t.[Date],
t.[Customer],
temp.[DateDiffFromPrevRow]
from sometable t
join @temp temp on temp.[ID] = t.[ID]
正如您在 fiddle 中所述,您使用 MySQL 5,7
您必须使用用户定义的变量。
我选择了 TIMEDIFF 来显示差异,因为你没有说明你需要哪些信息,所以我选择了这个,但是因为你有两个值,你可以使用不同的 mysql 函数
架构(MySQL v5.7)
CREATE TABLE `someTable` (
`ID` INT,
`POS` INT,
`Date` DATETIME,
`Customer` VARCHAR(64)
);
INSERT INTO `someTable` VALUES
(1, 10, "2017-03-10 08:00:00", "Peter"),
(2, 11, "2017-03-10 08:00:01", "Peter"),
(3, 12, "2017-03-10 08:00:04", "Peter"),
(4, 17, "2017-03-10 08:00:05", "Peter"),
(5, 16, "2017-03-10 08:00:08", "Karl"),
(6, 17, "2017-03-10 08:00:09", "Karl"),
(7, 10, "2017-03-10 08:00:12", "Peter"),
(8, 10, "2017-03-10 08:00:13", "Peter");
SELECT * FROM someTable
查询#1
SELECT
ID,
POS
,`Customer`
,IF(@date = `Date`,0,TIMEDIFF(`Date`, @date)) diff
,@date := `Date` 'Date'
FROM someTable, (SELECT @date := (SELECT MIN(`Date`) FROM someTable)) A;
| ID | POS | Customer | diff | Date |
| --- | --- | -------- | --------------- | ------------------- |
| 1 | 10 | Peter | 0 | 2017-03-10 08:00:00 |
| 2 | 11 | Peter | 00:00:01.000000 | 2017-03-10 08:00:01 |
| 3 | 12 | Peter | 00:00:03.000000 | 2017-03-10 08:00:04 |
| 4 | 17 | Peter | 00:00:01.000000 | 2017-03-10 08:00:05 |
| 5 | 16 | Karl | 00:00:03.000000 | 2017-03-10 08:00:08 |
| 6 | 17 | Karl | 00:00:01.000000 | 2017-03-10 08:00:09 |
| 7 | 10 | Peter | 00:00:03.000000 | 2017-03-10 08:00:12 |
| 8 | 10 | Peter | 00:00:01.000000 | 2017-03-10 08:00:13 |
如果您是运行 MySQL 8.0,只需使用lag()
和timetstampdiff()
。假设你想要与相同customer
的“先前”记录的日期差异,并且应该以秒表示:
select
t.*,
timestampdiff(
second,
lag(date, 1, date) over(partition by customer order by date),
date
) diff_seconds
from sometable t
每组的第一条记录相差 0
秒。
如果你是运行更早的版本,那么我会推荐相关子查询。虽然它可能比用户变量效率低一点,但它更安全,并且future-proof(用户变量计划在MySQL的未来版本中删除):
select
t.*,
timestampdiff(
second,
coalesce((select max(t1.date) from sometable t1 where t1.customer = t.customer and t1.date < t.date), date),
date
) diff_seconds
from sometable t
对于您的样本数据,both queries return:
| ID | POS | Date | Customer | diff_seconds |
| --- | --- | ------------------- | -------- | ------------ |
| 1 | 10 | 2017-03-10 08:00:00 | Peter | 0 |
| 2 | 11 | 2017-03-10 08:00:01 | Peter | 1 |
| 3 | 12 | 2017-03-10 08:00:04 | Peter | 3 |
| 4 | 17 | 2017-03-10 08:00:05 | Peter | 1 |
| 5 | 16 | 2017-03-10 08:00:08 | Karl | 0 |
| 6 | 17 | 2017-03-10 08:00:09 | Karl | 1 |
| 7 | 10 | 2017-03-10 08:00:12 | Peter | 7 |
| 8 | 10 | 2017-03-10 08:00:13 | Peter | 1 |