Mysql:对具有相同值的行进行分组,直到值更改为止

时间:2014-10-26 09:41:35

标签: mysql

我的表格如下:

   |ID| |Userid|    |ItemId|
    10        1            10
     9        1             9
     8        1             8
     7       38             7
     6       38             6
     5       38             5
     4        1             4
     3        1             3
     2        1             2
     1        1             1

我的sql请求是:

SELECT *
FROM nfeeds n1
WHERE EXISTS
(SELECT friendId
    FROM friends f WHERE friendId = n1.userid AND f.userid = 'my_userid')
GROUP BY userid
ORDER BY id DESC

结果是:

|ID|    |Userid|    |ItemId|
10        1            10
 7       38             7

我希望结果如下:

|ID|    |Userid|    |ItemId|
10        1            10
 7       38             7
 4        1             4

感谢。

3 个答案:

答案 0 :(得分:2)

注意:这假定连续的ID(无间隙)......

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table 
(ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,Userid INT NOT NULL
,ItemId INT NOT NULL
);

INSERT INTO my_table VALUES
(10 ,1,4),
(9  ,1,9),
(8  ,1,3),
(7 ,38,7),
(6 ,38,2),
(5 ,38,1),
(4  ,1,5),
(3  ,1,8),
(2  ,1,6),
(1  ,1,9);

SELECT x.* 
  FROM my_table x
  JOIN
     (
       SELECT MIN(c.id) id 
         FROM my_table a
         LEFT 
         JOIN my_table b 
           ON b.userid = a.Userid 
          AND b.id = a.id - 1 
         LEFT 
         JOIN my_table c 
           ON c.Userid = a.userid
          AND c.id >= a.id
         LEFT
         JOIN my_table d
           ON d.Userid = a.userid
          AND d.id = c.id + 1
        WHERE b.id IS NULL 
          AND c.id IS NOT NULL
          AND d.id IS NULL
        GROUP 
           BY a.id
     ) y
    ON y.id = x.id; 
+----+--------+--------+
| ID | Userid | ItemId |
+----+--------+--------+
|  4 |      1 |      5 |
|  7 |     38 |      7 |
| 10 |      1 |      4 |
+----+--------+--------+

http://sqlfiddle.com/#!2/ffc8e1/1

答案 1 :(得分:2)

MySQL使用变量提供了一种非常有效的方法。更有效的解决方案不使用临时表或任何连接。这是一种方法,假设您需要每个组的最大用户ID和项目ID(不清楚您是否需要最大值或第一个值):

select max(id) as userid, max(item_id) as item_id
from (select n.*,
             (@grp := if(@u = userid, @grp,
                         if(@u := userid, @grp + 1, @grp + 1)
                        )
             ) grp
      from nfeeds n cross join
           (select @grp := 0, @u := -1) vars
      order by id desc
     ) n
group by grp, userid;

答案 2 :(得分:1)

如果我正确理解了您尝试做的事情,那么您就拥有表nfeeds,其中包含由不同用户完成的记录序列(在您的示例序列中10,9,8用户1,7,6,5由用户38和序列4,3,2,1再次由用户1)。并且您希望为每个序列选择最新的记录。

我会再使用一个关系表sequences (id, user_id, max_nfeeds_id),但让我们继续你的例子。

您希望条件基于前一行,但 AFAIK MySQL并没有提供任何直接的解决方案来执行此操作。但...

You can join record with next id并比较用户ID。

SELECT nfeeds.*
FROM nfeeds
LEFT JOIN nfeeds AS nfeeds_prev ON nfeeds_prev.id = (
    SELECT MIN(id) FROM nfeeds AS nfeeds_inner 
    WHERE nfeeds_inner.id > nfeeds.id)
WHERE nfeeds_prev.userId IS NULL
    OR nfeeds.userId != nfeeds_prev.userId

IS NULL部分用于nfeeds_inner返回NULL(第一条记录)的情况。

我怀疑你是否能够利用这个索引,你总是会以Using Where结束所有行。