【问题标题】:SQL - group by column 1, order by column 2SQL - 按第 1 列分组,按第 2 列排序
【发布时间】:2019-12-18 04:43:59
【问题描述】:

这是我的情况,我有两个表分别名为 peoplecontacts

id name
1  dev one
2  dev two
3  dev three
4  dev five
5  dev four
id  person_id code_name updated_at
1   1         base1     2019-12-18 00:00:01
2   3         base2     2019-12-18 00:00:02
3   2         home      2019-12-18 00:00:03
4   2         home2     2019-12-18 00:00:04
5   3         work      2019-12-18 00:00:05
6   4         work      2019-12-18 00:00:06
7   5         base      2019-12-18 00:00:07
8   4         base2     2019-12-18 00:00:08
9   2         base      2019-12-18 00:00:09
10  5         work      2019-12-18 00:00:10

我正在尝试从联系人中获取结果,其中它按最近的 updated_at 排序并按 person_id 分组(注意:不完全是 sql“分组依据”),看起来类似于以下结果。

id  person_id code_name updated_at
10  5         work      2019-12-18 00:00:10
7   5         base      2019-12-18 00:00:07
9   2         base      2019-12-18 00:00:09
4   2         home2     2019-12-18 00:00:04
3   2         home      2019-12-18 00:00:03
8   4         base2     2019-12-18 00:00:08
6   4         work      2019-12-18 00:00:06
5   3         work      2019-12-18 00:00:05
2   3         base2     2019-12-18 00:00:02
1   1         base1     2019-12-18 00:00:01

目前我正在按 person_id descupdated_at desc 对联系人表进行排序,结果与我的预期有点接近,但并不完全正确。

查看结果时使用ORDER BY person_id DESC, updated_at DESC https://monosnap.com/file/xN0cuZAu2x2df4Q5qNDksKq5P3sEjU 联系id => 1 应该位于结果集的顶部,因为它是所有结果集中的最新更新。

注意:PostgreSQL 是我在这个案例中的第一个用例,但如果有任何区别,我也很高兴知道 MySQL。

【问题讨论】:

  • 但是您想要的输出没有按person_id 分组,因为这样每组只有一行。你的意思是“有序”而不是“分组”?
  • 也许您正在寻找ORDER BY person_id DESC, updated_at DESC
  • 是的@LaurenzAlbe它不完全是按person_id分组的,我可能会误导这里的“group by”术语,“group by”是指具有相同“person_id”的所有行都应该放在一起结果
  • @RickJames 是的,这是我目前的工作,但它并不完全正确,例如联系人表中的第 1 行已更新,ORDER BY person_id DESC, updated_at DESC 不会使其出现在结果集的顶部。跨度>
  • 为什么不呢?我认为@RickJames 是对的。

标签: mysql postgresql


【解决方案1】:

我在PostgreSQL 9.3中尝试了以下方法。

数据样本:

create table contact
(
    id int,
    person_id int,
    code_name varchar(20),
    updated_at timestamp
);

INSERT INTO contact VALUES
(1,1,'base1','2019-12-18 00:00:01'),
(2,3,'base2','2019-12-18 00:00:02'),
(3,2,'home','2019-12-18 00:00:03'),
(4,2,'home2','2019-12-18 00:00:04'),
(5,3,'work','2019-12-18 00:00:05'),
(6,4,'work','2019-12-18 00:00:06'),
(7,5,'base','2019-12-18 00:00:07'),
(8,4,'base2','2019-12-18 00:00:08'),
(9,2,'base','2019-12-18 00:00:09'),
(10,5,'work','2019-12-18 00:00:10');

查询:

DROP TABLE IF EXISTS TEMP_Stage_Table;

SELECT  string_agg(id::text,',' order by updated_at desc) id,
    person_id,
    string_agg(code_name,',' order by updated_at desc) code_name,
    string_agg(updated_at::text,',' order by updated_at desc) updated_at INTO TEMP_Stage_Table 
FROM contact
GROUP BY person_id
ORDER BY MAX(updated_at) DESC;

SELECT  regexp_split_to_table(t.id, E',') AS id,
    t.person_id, 
    regexp_split_to_table(t.code_name, E',') AS code_name,
    regexp_split_to_table(t.updated_at, E',') AS updated_at 
FROM TEMP_Stage_Table t;

输出:

【讨论】:

    【解决方案2】:

    (MySQL/MariaDB 语法)

    这将为一个人找到每个“行组”的“排序”,对吗?

    SELECT MAX(updated_at), person_id
        FROM tbl GROUP BY person_id ;
    

    所以,让我们这样利用它:

    SELECT y.*
        FROM (SELECT MAX(updated_at) AS latest, person_id
                   FROM tbl GROUP BY person_id ) AS x
        JOIN tbl AS y  USING(person_id)
        ORDER BY x.latest DESC, y.updated_at DESC;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-26
      • 1970-01-01
      • 2014-09-22
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      • 1970-01-01
      • 2016-11-07
      相关资源
      最近更新 更多