【问题标题】:Mysql: Group rows with same value until the value is changedMysql:对具有相同值的行进行分组,直到值更改
【发布时间】:2014-10-26 09:41:35
【问题描述】:

我的桌子是这样的:

   |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

谢谢。

【问题讨论】:

  • id 是否总是等于 item_id?多么方便!
  • 不清楚你在问什么,请解释一下
  • ...id 总是连续的吗?
  • 是的,我想选择最后一个相同值的 id

标签: mysql


【解决方案1】:

注意:这假定 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

【讨论】:

    【解决方案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;
    

    【讨论】:

      【解决方案3】:

      如果我正确理解您要执行的操作,您将拥有表 nfeeds,其中包含由不同用户完成的记录序列(在您的示例序列中,用户 1 10,9,8,@987654325 @ 由用户 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 遍历所有行结束。

      【讨论】:

        猜你喜欢
        • 2023-04-02
        • 1970-01-01
        • 1970-01-01
        • 2013-02-05
        • 2013-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多