简体   繁体   English

SQL在分组依据期间选择另一个具有最大值的列

[英]SQL select another column with max during group by

I have a sqlite database, and I am executing this query. 我有一个sqlite数据库,正在执行此查询。

SELECT
  thread.id as id,
  thread.title as title,
  post.posted as posted,
  user.username as username
FROM post
INNER JOIN thread ON post.thread_id = thread.id
INNER JOIN user ON post.user_id = user.id
ORDER BY posted desc;

This gives me the following rows 这给了我以下几行

5|Creating Thread|2017-07-23 08:05:15.730725|zrbecker
5|Creating Thread|2017-07-23 08:05:07.881327|zrbecker
4|This is a new thread|2017-07-23 05:14:08.513643|zrbecker
4|This is a new thread|2017-07-23 05:13:40.172866|admin
1|First Thread!|2017-07-23 05:10:43.772543|zrbecker
3|Here is a post|2017-07-23 04:58:10.999243|ralph
3|Here is a post|2017-07-23 04:52:49.060482|admin
3|Here is a post|2017-07-23 04:52:30.497092|admin
3|Here is a post|2017-07-23 04:50:53.800177|admin
2|Another Thread|2017-07-23 02:21:46.544810|ralph
1|First Thread!|2017-07-23 02:17:46.544810|ralph
1|First Thread!|2017-07-23 02:16:46.544810|admin

I want to do a "group by" where I group by thread.id, I want a last_posted, and first_posted column for the dates. 我想做一个“分组依据”,在这里我按thread.id分组,我想要一个last_posted和first_posted列作为日期。 But I also want last_username, and first_username to know the user that posted that post. 但我也希望last_username和first_username知道发布该帖子的用户。

This was my first attempt. 这是我的第一次尝试。

SELECT
  thread.id as id,
  thread.title as title,
  count(post.id) as number_posts,
  max(post.posted) as last_posted,
  user.username as last_username,
  min(post.posted) as first_posted,
  user.username as first_username
FROM post
INNER JOIN thread ON post.thread_id = thread.id
INNER JOIN user ON post.user_id = user.id
GROUP BY thread_id
ORDER BY last_posted desc;

There isn't really a good reason I should expect that to work. 我完全没有理由期望它能够正常工作。 It's seems like I need a max function that outputs both columns. 好像我需要一个输出两个列的max函数。 Not just the column I am taking the max of. 不只是我正在尽力而为的专栏。

Any help? 有什么帮助吗?

EDIT: Here is a .dump of my sqlite3 database 编辑:这是我的sqlite3数据库的.dump

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE thread (
        id INTEGER NOT NULL,
        title VARCHAR(80),
        PRIMARY KEY (id)
);
INSERT INTO thread VALUES(1,'First Thread!');
INSERT INTO thread VALUES(2,'Another Thread');
INSERT INTO thread VALUES(3,'Here is a post');
INSERT INTO thread VALUES(4,'This is a new thread');
INSERT INTO thread VALUES(5,'Creating Thread');
CREATE TABLE user (
        id INTEGER NOT NULL,
        username VARCHAR(30) NOT NULL,
        password VARCHAR(50) NOT NULL,
        PRIMARY KEY (id),
        UNIQUE (username)
);
INSERT INTO user VALUES(1,'admin','test123');
INSERT INTO user VALUES(2,'ralph','password123');
INSERT INTO user VALUES(3,'zrbecker','helloworld');
CREATE TABLE post (
        id INTEGER NOT NULL,
        user_id INTEGER,
        thread_id INTEGER,
        message TEXT NOT NULL,
        posted DATETIME,
        PRIMARY KEY (id),
        FOREIGN KEY(user_id) REFERENCES user (id),
        FOREIGN KEY(thread_id) REFERENCES thread (id)
);
INSERT INTO post VALUES(1,1,1,'First Post!','2017-07-23 02:16:46.544810');
INSERT INTO post VALUES(2,2,1,'Second post!','2017-07-23 02:17:46.544810');
INSERT INTO post VALUES(3,2,2,'Another post','2017-07-23 02:21:46.544810');
INSERT INTO post VALUES(4,1,3,'Lorem Ipsum ','2017-07-23 04:50:53.800177');
INSERT INTO post VALUES(5,1,3,'test test','2017-07-23 04:52:30.497092');
INSERT INTO post VALUES(6,1,3,'test trest test','2017-07-23 04:52:49.060482');
INSERT INTO post VALUES(7,2,3,'Hello There','2017-07-23 04:58:10.999243');
INSERT INTO post VALUES(8,3,1,'hello','2017-07-23 05:10:43.772543');
INSERT INTO post VALUES(9,1,4,'This is my message','2017-07-23 05:13:40.172866');
INSERT INTO post VALUES(10,3,4,'hello','2017-07-23 05:14:08.513643');
INSERT INTO post VALUES(11,3,5,'This is a thread','2017-07-23 08:05:07.881327');
INSERT INTO post VALUES(12,3,5,'New post','2017-07-23 08:05:15.730725');
COMMIT;

I ended up coming up with a SQL query that seems to work. 我最终想到了一个似乎有效的SQL查询。 Seems quite complicated though. 虽然看起来很复杂。 Hoping for something much simpler. 希望有更简单的东西。

Here is the query: 这是查询:

SELECT
  thread.id AS id,
  thread.title AS title,
  thread.post_count AS post_count,
  thread.last_posted AS last_posted,
  last_user.username AS last_username,
  thread.first_posted AS first_posted,
  first_user.username AS first_username
FROM (
  SELECT
    thread.id AS id,
    thread.title AS title,
    count(post.id) AS post_count,
    max(post.posted) AS last_posted,
    min(post.posted) AS first_posted
  FROM thread
  INNER JOIN post ON post.thread_id = thread.id
  GROUP BY thread.id
) AS thread
INNER JOIN post AS last_post
  ON last_post.thread_id = thread.id
  AND last_post.posted = thread.last_posted
INNER JOIN post AS first_post
  ON first_post.thread_id = thread.id
  AND first_post.posted = thread.first_posted
INNER JOIN user AS last_user ON last_post.user_id = last_user.id
INNER JOIN user AS first_user ON first_post.user_id = first_user.id
ORDER BY last_posted DESC;

Desired output looks like this: 所需的输出如下所示:

5|Creating Thread|2|2017-07-23 08:05:15.730725|zrbecker|2017-07-23 08:05:07.881327|zrbecker
4|This is a new thread|2|2017-07-23 05:14:08.513643|zrbecker|2017-07-23 05:13:40.172866|admin
1|First Thread!|3|2017-07-23 05:10:43.772543|zrbecker|2017-07-23 02:16:46.544810|admin
3|Here is a post|4|2017-07-23 04:58:10.999243|ralph|2017-07-23 04:50:53.800177|admin
2|Another Thread|1|2017-07-23 02:21:46.544810|ralph|2017-07-23 02:21:46.544810|ralph

Another Edit: My ultimate goal is to craft a SQLAlchemy expression that will do this for me. 另一个编辑:我的最终目标是制作一个SQLAlchemy表达式,该表达式将为我完成此任务。 When I couldn't figure out how to do it with the ORM, I decided to try to come up with a raw SQL query that could guide me. 当我不知道如何使用ORM时,我决定尝试提出一个可以指导我的原始SQL查询。 Any advice that would move me in that direction would be nice. 任何可以使我朝这个方向发展的建议都很好。

Thanks. 谢谢。

Try the query below 请尝试以下查询

with postData as(
SELECT
post.*
,row_number() over (partition by  post.thread_id order by post.posted desc) descRowNumber
,row_number() over (partition by  post.thread_id order by post.posted ) ascRowNumber
FROM post
)
SELECT thread.id AS id,
thread.title AS title,
last_posted.posted AS last_postedDate,
last_user.username AS last_username,
first_posted.posted AS first_postedDate,
first_user.username AS first_username 
from
thread left join
  (select id,thread_id from postData where ascRowNumber=1) first_posted on first_posted.thread_id=thread.id
left join  
  (select id,thread_id from postData where descRowNumber=1) last_posted on last_posted.thread_id=thread.id
left JOIN [user] AS first_user ON first_posted.user_id = first_user.id
left JOIN [user] AS last_user ON last_posted.user_id = last_user.id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM