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

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

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

提前非常感谢你:)

【问题讨论】:

  • 您的服务器上精确的 MySQL 版本是多少?
  • 之前输入是什么意思 - 是客户输入的吗?

标签: mysql sql datetime subquery window-functions


【解决方案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 标签
      猜你喜欢
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-28
      • 2013-03-03
      • 1970-01-01
      • 2012-10-08
      • 2019-07-27
      相关资源
      最近更新 更多