1

要将一行与前一行进行比较,我JOIN将一个表与前一行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)添加到表中,我如何将查询限制为仅区分特定用户?向两个查询添加一个简单的 WHERE 子句SELECT将不起作用,因为整个前提取决于序列ids。我想我可以将数据移动到一个临时表中,但如果有一个更清洁、更有效的解决方案,那么我会使用它。

我的意图是添加一个WHERE user='someUser'子句,该子句的差异将仅针对特定用户,而不是整个表。

这是一个工作sqlfiddle。我想修改此查询,使其仅适用于WHERE name='a',结果将是id=9, data=305, diff=125

4

5 回答 5

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)

如果 previous 是NULL,则返回列数据的值。因此,没有前一行的行的差异为零。

如果您有更多问题,请随时提问。

PS:这个查询甚至可能比你必须自加入的查询更快。

于 2013-03-27T16:53:55.813 回答
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

在此处查看小提琴。这是标准 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

请看这里

于 2013-03-29T17:25:56.530 回答
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

SQLFiddle演示

于 2013-04-01T18:00:54.050 回答
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;
于 2013-04-01T18:16:57.390 回答
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;
于 2013-03-18T11:18:22.207 回答