假设我有一张这样的table:
| 身份证|日期|名称|价值|
| --------------|--------------|--------------|--------------|
| 0| 2017-01-14 2017-01-14|福|一个|
| 1| 2017-01-17 2017-01-17|杆|两个|
| 二|2017-01-18 2017-01-18|约翰|五|
| 三|2017-01-19 2017-01-19 2017-01-19|母鹿|十|
(其中date
不一定需要排序)
我希望能够选择 previous 行的一些值(基于date
)。这样的功能可以通过以下查询来实现:
SELECT
*,
(SELECT
name
FROM
example e2
WHERE
e2.dt < e1.dt
ORDER BY dt DESC
LIMIT 1
) as prev_name
FROM example e1
结果表:
| 身份证|dt|名称|价值|上一个名称|
| --------------|--------------|--------------|--------------|--------------|
| 0| 2017-01-14 2017-01-14|福|一个|(空)|
| 1| 2017-01-17 2017-01-17|杆|两个|福|
| 二|2017-01-18 2017-01-18|约翰|五|杆|
| 三|2017-01-19 2017-01-19 2017-01-19|母鹿|十|约翰|
现在,这个工作正常。但是,如果我可以轻松地从前一行中选择 * 多个 * 列,则会更好,结果如下:
| 身份证|dt|名称|价值|上一个名称|前值|上一个dt|
| --------------|--------------|--------------|--------------|--------------|--------------|--------------|
| 0| 2017-01-14 2017-01-14|福|一个|(空)|(空)|(空)|
| 1| 2017-01-17 2017-01-17|杆|两个|福|一个|2017-01-14 2017-01-14|
| 二|2017-01-18 2017-01-18|约翰|五|杆|两个|2017-01-17 2017-01-17|
| 三|2017-01-19 2017-01-19 2017-01-19|母鹿|十|约翰|五|2017-01-18 2017-01-18|
这当然可以通过简单地将子查询(SELECT [..] FROM example e2 ...)
多次复制到查询中来实现,但我想这不是最好的方法。我发现了几个关于SO的问题,要么解决“如何从前一行选择记录”,要么解决“如何使用子查询选择多个列”的问题,但不能同时解决这两个问题。后一个问题主要是通过使用JOIN
语句来解决的,但我认为这与“前一行”的情况是不可组合的。所以我的问题是有什么更好的方法来产生最后一个结果,而不是为我们需要的每一列复制一个子查询?
**编辑。**作为一个额外的约束,我没有包括在原来的问题中,“previous”实际上可以是与前一行不同的东西,而是“满足条件的前一行”。假设我的表包含一个额外的boolean
列b
身份证 | dt | 名称 | 价值 | B |
---|---|---|---|---|
0 | 2017-01-14 2017-01-14 | 福 | 一个 | 1 |
1 | 2017-01-17 2017-01-17 | 杆 | 两个 | 0 |
二 | 2017-01-18 2017-01-18 | 约翰 | 五 | 1 |
三 | 2017-01-19 2017-01-19 2017-01-19 | 母鹿 | 十 | 0 |
我希望“previous row”是b = 1
的前一行,因此期望的结果是:
| 身份证|dt|名称|价值|B|上一个名称|前值|上一个dt|
| --------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|
| 0| 2017-01-14 2017-01-14|福|一个|1|(空)|(空)|(空)|
| 1| 2017-01-17 2017-01-17|杆|两个|0|福|一个|2017-01-14 2017-01-14|
| 二|2017-01-18 2017-01-18|约翰|五|1|福|一个|2017-01-14 2017-01-14|
| 三|2017-01-19 2017-01-19 2017-01-19|母鹿|十|0|约翰|五|2017-01-18 2017-01-18|
我认为这仍然可以通过James Scott的答案来实现,只需在b = 1
时使用IF
-语句更新变量,但在这种情况下可能有另一种解决方案。
**EDIT.**SQLfiddle
2条答案
按热度按时间hc8w905p1#
类似这样的操作将返回'previous'行的id。
我将把返回与此行关联的其余数据的工作留给读者作为练习。
elcex8rz2#
看起来是会话变量的一个很好的用例,如果你只想要前一行,你可以使用
ORDER BY
来获得不同的结果。当我第一次发布的时候就搞砸了,注意变量必须在从前一行返回后设置。若要对列重新排序(如果需要),可以将此查询 Package 在另一个查询中,然后重新排序结果列。
如果你还需要什么就告诉我,
致上,
詹姆斯