Mysql 使用WHERE子句从上一个匹配行查询差异
要将一行与前一行区分开来,我要将一个表连接到它自己,并与前一个Mysql 使用WHERE子句从上一个匹配行查询差异,mysql,Mysql,要将一行与前一行区分开来,我要将一个表连接到它自己,并与前一个id(主键)进行比较: 我如何将其限制为数据的特定子集?例如,如果表中添加了一列user VARCHAR(32),如何将查询限制为仅区分特定用户?在两个SELECT查询中添加一个简单的WHERE子句将不起作用,因为整个前提取决于顺序ids。我想我可以将数据移动到一个临时表中,但是如果有一个更干净、更高效的解决方案,那么我会使用它 我的意图是添加一个WHERE user='someUser'子句,对于该子句,diff将仅对特定用户而不是
id
(主键)进行比较:
我如何将其限制为数据的特定子集?例如,如果表中添加了一列user VARCHAR(32)
,如何将查询限制为仅区分特定用户?在两个SELECT
查询中添加一个简单的WHERE子句将不起作用,因为整个前提取决于顺序id
s。我想我可以将数据移动到一个临时表中,但是如果有一个更干净、更高效的解决方案,那么我会使用它
我的意图是添加一个WHERE user='someUser'
子句,对于该子句,diff将仅对特定用户而不是整个表进行diff
这是一张工作票。我想修改此查询,使其仅适用于
WHERE name='a'
,因此结果将是id=9,data=305,diff=125
这不是一个好的做法,但有时我会像这样加入半联接
SELECT
t1.id,
t1.data,
t1.data- t3.data AS diff
FROM tablename t1
LEFT JOIN tablename t2
ON t1.id = t2.id
LEFT JOIN tablename t3
ON t3.data = (SELECT
data
FROM tablename
WHERE id > t1.id
LIMIT 1)
ORDER BY diff DESC
LIMIT 1;
这不是一个好的练习,但我有时会像这样加入半连接
SELECT
t1.id,
t1.data,
t1.data- t3.data AS diff
FROM tablename t1
LEFT JOIN tablename t2
ON t1.id = t2.id
LEFT JOIN tablename t3
ON t3.data = (SELECT
data
FROM tablename
WHERE id > t1.id
LIMIT 1)
ORDER BY diff DESC
LIMIT 1;
给你:
SELECT id, data, data - COALESCE(previous, data) as diff FROM (
SELECT
t.*,
@prev AS previous,
@prev:=t.data
FROM
tablename t
, (SELECT @prev:=NULL) var
where name = 'a'
)sq
order by diff desc
limit 1
说明:
, (SELECT @prev:=NULL) var
变量的初始化
@prev AS previous,
@prev:=t.data
在第一列中输出变量的当前值,在第二列中指定当前行的值
COALESCE(previous, data)
如果previous为NULL
,则返回列数据的值。因此,没有前一行的行的差异为零
如果您还有更多问题,请随时提问
备注:此查询可能比您必须自行加入的查询更快。给您:
SELECT id, data, data - COALESCE(previous, data) as diff FROM (
SELECT
t.*,
@prev AS previous,
@prev:=t.data
FROM
tablename t
, (SELECT @prev:=NULL) var
where name = 'a'
)sq
order by diff desc
limit 1
说明:
, (SELECT @prev:=NULL) var
变量的初始化
@prev AS previous,
@prev:=t.data
在第一列中输出变量的当前值,在第二列中指定当前行的值
COALESCE(previous, data)
如果previous为NULL
,则返回列数据的值。因此,没有前一行的行的差异为零
如果您还有更多问题,请随时提问
附言:这个查询可能比你必须自行加入的查询更快。如果我正确理解你的问题,我认为你应该使用如下方式:
SELECT t1.id, t1.data data_curr, t2.data data_prev, t1.data - t2.data data_diff
FROM (
SELECT t1.id, t1.data, MAX(t2.id) max_id
FROM
tablename t1 INNER JOIN tablename t2
ON t1.name = t2.name
AND t1.id > t2.id
WHERE
t1.name = 'a'
GROUP BY
t1.id, t1.data
) t1 INNER JOIN tablename t2
ON t1.max_id = t2.id
请看小提琴。这是标准的SQL,应该适用于任何DBMS
但是,如果您只需要最后一个差异数据,您可以在主查询中使用LIMIT 1
(按ID DESC排序)来获取name='a'所在的最后一个数据,然后使用LIMIT 1,1
来获取最后第二个数据:
SELECT id, data data_curr,
data -
(SELECT data FROM tablename WHERE name='a' ORDER BY id DESC LIMIT 1,1) data_diff
FROM tablename
WHERE name='a'
ORDER BY id DESC
LIMIT 1
请看。如果我正确理解了你的问题,我认为你应该使用以下内容:
SELECT t1.id, t1.data data_curr, t2.data data_prev, t1.data - t2.data data_diff
FROM (
SELECT t1.id, t1.data, MAX(t2.id) max_id
FROM
tablename t1 INNER JOIN tablename t2
ON t1.name = t2.name
AND t1.id > t2.id
WHERE
t1.name = 'a'
GROUP BY
t1.id, t1.data
) t1 INNER JOIN tablename t2
ON t1.max_id = t2.id
请看小提琴。这是标准的SQL,应该适用于任何DBMS
但是,如果您只需要最后一个差异数据,您可以在主查询中使用LIMIT 1
(按ID DESC排序)来获取name='a'所在的最后一个数据,然后使用LIMIT 1,1
来获取最后第二个数据:
SELECT id, data data_curr,
data -
(SELECT data FROM tablename WHERE name='a' ORDER BY id DESC LIMIT 1,1) data_diff
FROM tablename
WHERE name='a'
ORDER BY id DESC
LIMIT 1
请查看。根据您的数据,数据字段的值似乎在上升,差值应始终为正值 这应该行得通
SELECT
id,
max(data)-min(data) as diff,
max(data) as data
name
FROM
(
SELECT
id,
data,
name
FROM
tablename
WHERE
name = 'a'
ORDER BY
id desc
LIMIT 2
) t
GROUP BY
name
演示给定您的数据,数据字段的值似乎在上升,差值应始终为正值 这应该行得通
SELECT
id,
max(data)-min(data) as diff,
max(data) as data
name
FROM
(
SELECT
id,
data,
name
FROM
tablename
WHERE
name = 'a'
ORDER BY
id desc
LIMIT 2
) t
GROUP BY
name
演示您也可以这样做-尽管tombom的版本可以更好地扩展
SELECT a.id
, a.data
, a.name
, a.data-b.data ttl
FROM
( SELECT x.*
, COUNT(*) rank
FROM tablename x
JOIN tablename y
ON y.name = x.name
AND y.id >=x.id
GROUP
BY x.id
) a
JOIN
( SELECT x.*
, COUNT(*) rank
FROM tablename x
JOIN tablename y
ON y.name = x.name
AND y.id >=x.id
GROUP
BY x.id
) b
ON b.name = a.name
AND b.rank = a.rank + 1
WHERE a.rank = 1;
您也可以这样做-虽然tombom的版本可以更好地扩展
SELECT a.id
, a.data
, a.name
, a.data-b.data ttl
FROM
( SELECT x.*
, COUNT(*) rank
FROM tablename x
JOIN tablename y
ON y.name = x.name
AND y.id >=x.id
GROUP
BY x.id
) a
JOIN
( SELECT x.*
, COUNT(*) rank
FROM tablename x
JOIN tablename y
ON y.name = x.name
AND y.id >=x.id
GROUP
BY x.id
) b
ON b.name = a.name
AND b.rank = a.rank + 1
WHERE a.rank = 1;
谢谢Raheel Shan,但这不允许我将查询限制为仅针对特定用户进行差异化。我会让问题的这一部分更清楚。谢谢Raheel Shan,但这不允许我将查询限制为仅针对特定用户进行差异化。我会让问题的这一部分更清楚。期望结果中的id是9。您的sqlfiddle中没有16行。只是说说而已,所以没有人感到困惑。不编辑我自己,因为我提供了答案,没有人会说我作弊:)谢谢tombom,你是正确的,我做了编辑。期望结果中的id是9。您的sqlfiddle中没有16行。只是说说而已,所以没有人感到困惑。不编辑自己,因为我提供了答案,没有人会说我作弊:)谢谢tombom,你是正确的,我做了编辑。谢谢,这太棒了。我不知道如何使用
COALESCE
,我喜欢你对MySQL会话变量的雄辩使用。这是一个非常有用的答案,有一个非常聪明的解决方案。谢谢你tombom!谢谢,这太棒了。我不知道如何使用COALESCE
,我喜欢你对MySQL会话变量的雄辩使用。这是一个非常有用的答案,有一个非常聪明的解决方案。谢谢你tombom!谢谢你,阿卡什。这似乎返回了最后的差异,而不是最高的差异。谢谢你,阿卡什。这似乎返回了最后的差异,而不是最高的差异。谢谢,这很有创意。谢谢,这很有创意。