迭代SQL中的数据[关闭]

Posted

技术标签:

【中文标题】迭代SQL中的数据[关闭]【英文标题】:Iterate over data in SQL [closed] 【发布时间】:2020-08-31 13:17:24 【问题描述】:

拥有此数据集:https://www.db-fiddle.com/f/6vmgx4krsgMRgprDjErdqu/0

我想要一个额外的列来显示与之前条目的时间距离,我该如何实现?

提前非常感谢你:)

【问题讨论】:

您的服务器上精确的 mysql 版本是多少? 之前输入是什么意思 - 是客户输入的吗? 【参考方案1】:

正如您在小提琴中所说,您使用 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 |

View on DB Fiddle

【讨论】:

【参考方案2】:

如果您运行的是 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 秒的差异。

如果您运行的是早期版本,那么我建议您使用相关子查询。虽然它的效率可能比用户变量低一点,但它更安全,而且面向未来(计划在未来版本的 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            |

【讨论】:

【参考方案3】:

像这样的东西不能解决问题:

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]

【讨论】:

问题是 [mysql]-tagged,而不是 [sql-server]。 在 MySQL 8.0 版本中还引入了 MySQL windows 函数。 dbfiddle 链接使用的是 MySQL 5.7,因此他甚至无法使用 LAG 我的错,错过了看到 mysql 标签

以上是关于迭代SQL中的数据[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何仅使用 C++ 中的迭代器正确迭代 3D 向量? [关闭]

TypeError:'int'对象不可迭代,使用 Python 3 [关闭]

如何在c ++中迭代数组中的唯一元素[关闭]

输出累积每次迭代而不是重置[关闭]

用于迭代服务器的 SQL Server 脚本

用于迭代服务器的 SQL Server 脚本第 2 部分