mysql - 从 MySQL 中的上一行中选择多列

标签 mysql subquery

假设我有一个这样的表:

| id |       date | name | value |
|----|------------|------|-------|
|  0 | 2017-01-14 |  foo |   one |
|  1 | 2017-01-17 |  bar |   two |
|  2 | 2017-01-18 | john |  five |
|  3 | 2017-01-19 |  doe |   ten |

(其中 date 不一定要排序)

我希望能够选择 行的一些值(基于日期)。这样的功能可以通过以下查询来实现:

SELECT 
  *, 
  (SELECT 
     name 
   FROM 
     example e2 
   WHERE 
     e2.dt < e1.dt 
   ORDER BY dt DESC 
   LIMIT 1
   ) as prev_name 
FROM example e1

结果表:

| id |         dt | name | value | prev_name |
|----|------------|------|-------|-----------|
|  0 | 2017-01-14 |  foo |   one |    (null) |
|  1 | 2017-01-17 |  bar |   two |       foo |
|  2 | 2017-01-18 | john |  five |       bar |
|  3 | 2017-01-19 |  doe |   ten |      john |

现在,这工作得很好。但是,如果我可以轻松地从上一行中选择 多个 列,则结果会更好:

| id |         dt | name | value | prev_name | prev_value |    prev_dt |
|----|------------|------|-------|-----------|------------|------------|
|  0 | 2017-01-14 |  foo |   one |    (null) |     (null) |     (null) |
|  1 | 2017-01-17 |  bar |   two |       foo |        one | 2017-01-14 |
|  2 | 2017-01-18 | john |  five |       bar |        two | 2017-01-17 |
|  3 | 2017-01-19 |  doe |   ten |      john |       five | 2017-01-18 |

这当然可以通过简单地将子查询 (SELECT [..] FROM example e2 ...) 多次复制到查询中来完成,但我想这不是更好的方法去。我发现了几个关于 SO 的问题,要么“如何从前一行中选择记录”“如何使用子查询选择多列”问题,但不能同时解决这两个问题.后一个问题主要通过使用 JOIN 语句来解决,但我认为这不能与“上一行”的情况结合使用。所以我的问题是:什么是生成最后结果的更好方法,而不是为我们需要的每一列复制子查询?

编辑。作为一个额外的约束,我没有在原始问题中包含,“previous”实际上可能与前一行不同,而是“满足条件的前一行” ”。所以假设我的表包含一个额外的 booleanb

| id |         dt | name | value | b |
|----|------------|------|-------|---|
|  0 | 2017-01-14 |  foo |   one | 1 |
|  1 | 2017-01-17 |  bar |   two | 0 |
|  2 | 2017-01-18 | john |  five | 1 |
|  3 | 2017-01-19 |  doe |   ten | 0 |

我希望“前一行”是 b = 1 的前一行,因此所需的结果将是:

| id |         dt | name | value | b | prev_name | prev_value |    prev_dt |
|----|------------|------|-------|---|-----------|------------|------------|
|  0 | 2017-01-14 |  foo |   one | 1 |    (null) |     (null) |     (null) |
|  1 | 2017-01-17 |  bar |   two | 0 |       foo |        one | 2017-01-14 |
|  2 | 2017-01-18 | john |  five | 1 |       foo |        one | 2017-01-14 |
|  3 | 2017-01-19 |  doe |   ten | 0 |      john |       five | 2017-01-18 |

我认为这仍然可以通过 James Scott 的回答来完成,只需在 b = 1 时更新变量,使用 IF 语句,但也许有在这种情况下可能的另一种解决方案。

编辑 SQLfiddle

最佳答案

像这样的东西将返回“上一个”行的 ID。

 SELECT x.*
      , MAX(y.id) prev_id
   FROM example x
   LEFT
   JOIN example y
     ON y.id < x.id 
    AND y.b = 1
  GROUP
     BY x.id;

我将返回与该行相关的其余数据作为读者的练习。

关于mysql - 从 MySQL 中的上一行中选择多列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45880647/

相关文章:

mysql - 关系数据库中的数据粒度

mysql - SQL IN () 包含 NULL 值

php - 将 CSV 插入 MySQL

mysql - 使用 INNER JOIN 时正确的索引/查询

php - 如何将同一个表中的多个用户信息回显并分离到他们的每个页面

mysql - 尝试优化通过投票事件列出选民的查询

java - 使用 JOOQ 更新多个表

mysql - 如何进行嵌套 bool 过滤器以在elasticsearch中的同一字段上查找精确匹配的值?

MySQL 检查用户上次登录时间戳是否总是小于 session 时间戳

php - 过滤mysql查询结果