【问题标题】:Selecting latest row of record with distinct parameter选择具有不同参数的最新记录行
【发布时间】:2013-11-27 12:25:18
【问题描述】:

我想选择一个包含特定用户的非重复记录列表(在user_touser_from 中)。我想检索其他用户以及该记录中的最新内容。该列表不得在所选的其他用户中重复。

例如,我有以下一组记录

id   user_to   user_from   content     time
1      1          2          ABC    2013-11-05  
2      4          2          BBC    2013-11-06  
3      3          1          CBC    2013-11-07  
4      5          1          ABC    2013-11-08 
5      1          2          AAC    2013-11-09  
6      5          1          ABB    2013-11-10 
7      3          4          CBC    2013-11-11  
8      1          2          ACC    2013-11-12 

在这种情况下,如果要提供的参数是1,我想选择记录3,6,8,其他的没有被选择,因为它们是重复的和旧的,或者它们不涉及1。 我查看了this post 并尝试了这样的事情:

 SELECT u, content, date FROM(
       (SELECT 
                user_from AS u, 
                MAX(time) AS date, 
                content
            FROM t1 
                WHERE user_to = :user 
            ) 
                UNION
            (SELECT 
                user_to AS u, 
                MAX(time) AS date, 
                content
            FROM t1  
                WHERE user_from = :user 
            ) 
        ) t2
WHERE date IN (SELECT MAX(date) FROM t2 GROUP BY u)

但是不,做不到。

知道如何编写查询吗?谢谢!

【问题讨论】:

  • 为什么不是 4 注册表而不是 3?因为你说要么是重复的,要么是旧的,但旧的是 3 而不是 4!
  • 我的意思是(它们是重复的并且更旧)或者(它们不涉及 1)。记录 4 涉及另一个用户 5(作为 user_to),它在 6 中有更新的记录。记录 3 涉及没有更新记录的用户 3。很抱歉造成混乱。
  • 即使您编辑了您想要的数据也不适合显示的示例示例。如果您想要用户 1(从和到)且不重复且是最大日期的所有内容,则结果应为:3、4、6 和 8。请查看您的数据。
  • 更好的 3、4、5、6 和 8。在此处查看:sqlfiddle.com/#!2/198d1e/8
  • 不应选择记录 4,因为有更新的记录 6 也涉及用户 5。不应选择记录 5,因为有更新的记录 8 也涉及用户 2。我想选择对方的用户(所以如果 1 是 user_to,我想要 user_from,如果 1 是 user_from,我想要 user_to),因此,你可以在我的原始 sql 中看到,我有两个具有相同别名 u 的查询的联合

标签: mysql select group-by distinct union


【解决方案1】:

您的查询应该是这样的:

 select m.* from 
 message m,
 ( select user_to,
          user_from, 
          max(dtime) mxdate 
     from message 
    where user_from = 1 or user_to = 1
    group by user_to, user_from) m2
 where m.dtime = m2.mxdate
   and (m.user_from = 1 or m.user_to = 1)

在 fiddle 看到它:http://sqlfiddle.com/#!2/13d4e/4

正如您在 cmets 中所问的:好的。但由于我只想要另一个用户的 user_id,有没有办法在 user_from=1 时只选择 user_to ,在 user_to=1 时只选择 user_from ?

select if(m.user_to=1,m.user_from,m.user_to) as user, 
       m.content, 
       m.dtime
  from 
    message m,
    ( select user_to,
             user_from, 
             max(dtime) mxdate 
        from message 
       where user_from = 1 or user_to = 1
       group by user_to, user_from) m2
 where m.dtime = m2.mxdate
   and (m.user_from = 1 or m.user_to = 1)

在这里查看:http://sqlfiddle.com/#!2/13d4e/5

【讨论】:

  • 哦..我的例子不够好...我的意思是用户 1 可以在 user_from 或 user_to 中。请参阅我编辑的示例。
  • 这是不对的。 'group by user_to, user_from' 不能满足唯一对话的要求。
  • @Strawberry 我认为,就像我一开始一样,您误解了 OP 的要求。如果您查看 cmets,您会发现这正是他想要的。
  • 好吧,在这种情况下,我不能再假装我真的理解这个要求了 :-(。你可能是正确的,但无论哪种方式,你的解决方案仍然假设 dtime 是唯一的(对于用户 1 来说很好)无论如何)。我同意这很有可能,但我不确定是否应该依赖它。
  • 我明白你在说什么,在我的一个最大(日期)中有一个日期像“2013-11-11”和其他一些用户(从和到)作为这个日期匹配我的加入,但如您所见,我在外部查询中使用与 and (m.user_from = 1 or m.user_to = 1) 内部相同的过滤器
【解决方案2】:
DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id   INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,user_to   INT NOT NULL
,user_from INT NOT NULL  
,content   CHAR(3) NOT NULL  
,dt DATE NOT NULL
);

INSERT INTO my_table VALUES
(1,1,2,'ABC','2013-11-05'),
(2,4,2,'BBC','2013-11-06'),
(3,3,1,'CBC','2013-11-07'),
(4,5,1,'ABC','2013-11-08'),
(5,1,2,'AAC','2013-11-09'),
(6,5,1,'ABB','2013-11-10'),
(7,3,4,'CBC','2013-11-11'),
(8,1,2,'ACC','2013-11-12'); 

SELECT x.* 
  FROM my_table x 
  JOIN 
     ( SELECT LEAST(user_to,user_from) l
            , GREATEST(user_to,user_from) g
            , MAX(dt) max_dt FROM my_table 
        GROUP 
           BY LEAST(user_to,user_from)
            , GREATEST(user_to,user_from)
     ) y 
    ON y.l = LEAST(x.user_to,x.user_from) 
   AND y.g = GREATEST(x.user_to,x.user_from) 
   AND y.max_dt = x.dt 
 WHERE 1 IN (x.user_to,x.user_from);
+----+---------+-----------+---------+------------+
| id | user_to | user_from | content | dt         |
+----+---------+-----------+---------+------------+
|  3 |       3 |         1 | CBC     | 2013-11-07 |
|  6 |       5 |         1 | ABB     | 2013-11-10 |
|  8 |       1 |         2 | ACC     | 2013-11-12 |
+----+---------+-----------+---------+------------+

【讨论】:

    【解决方案3】:

    如果过滤为“1”,则将此添加到@Jorge Campos 的查询中

    where user_from = 1 OR user_to=1
    

    【讨论】:

    • 我只能选择user_from。即使我还选择了 user_to 字段,我也无法确定哪个 (user_to/user_from ?) 是我想要的值,因为我不想要 user=1 的值,而只想要另一个
    • 使用更正的答案@Jorge Campos,如果设置为“1”,查询将选择 user_from 或 user_to。或者我们不明白你想要什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    • 1970-01-01
    • 2014-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多