要与前一行区分一行,我JOIN
将一个表{self}并与之前的id
(主键)进行比较:
CREATE TABLE `tablename` (
id INT(5) PRIMARY KEY AUTO_INCREMENT,
data INT
);
SELECT t1.id, t1.data, t1.data-(SELECT data FROM tablename WHERE id=t1.id-1) AS diff
FROM tablename t1 LEFT JOIN tablename t2 ON t1.id = t2.id
ORDER BY diff DESC LIMIT 1;
如何将此限制仅限于特定的数据子集?例如,如果将列user VARCHAR(32)
添加到表中,我如何将查询限制为仅区分特定用户?为两个SELECT
查询添加一个简单的WHERE子句将不起作用,因为整个前提依赖于顺序id
。我想我可以将数据移动到临时表中,但如果有更清洁,更有效的解决方案,那么我会使用它。
我的意图是添加一个WHERE user='someUser'
子句,diff只为特定用户而不是整个表区分。
这是一个有效的sqlfiddle。我想修改此查询,使其仅适用于WHERE name='a'
,因此结果为id=9, data=305, diff=125
。
答案 0 :(得分:2)
你走了:
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)
如果之前是NULL
,则返回列数据的值。因此,没有前一行的行的diff为零。
随意询问您是否有更多问题。
P.S。:这个查询甚至比你必须自我加入的查询更快。
答案 1 :(得分:2)
如果我理解你的问题,我认为你应该使用这样的东西:
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
请参阅小提琴here。这是标准SQL,适用于任何DBMS。
但是,如果您只需要LAST diff数据,则可以在主查询中使用LIMIT 1
(按ID DESC排序)以获取name ='a'的最后一个数据,然后{{1}获取倒数第二个数据:
LIMIT 1,1
请看here。
答案 2 :(得分: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
答案 3 :(得分: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;
答案 4 :(得分:0)
嗯,这不是一个好习惯,但我有时会像这样加入半连接
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;