简体   繁体   English

POSTGRESQL:如何选择每组的第一行?

[英]POSTGRESQL : How to select the first row of each group?

With this query :有了这个查询:

WITH responsesNew AS
(
  SELECT DISTINCT responses."studentId", notation, responses."givenHeart", 
  SUM(notation + responses."givenHeart") OVER (partition BY responses."studentId" 
  ORDER BY responses."createdAt") AS total, responses."createdAt",  
  FROM responses
)
SELECT responsesNew."studentId", notation, responsesNew."givenHeart", total, 
responsesNew."createdAt"
FROM responsesNew
WHERE total = 3
GROUP BY responsesNew."studentId", notation, responsesNew."givenHeart", total, 
responsesNew."createdAt"
ORDER BY responsesNew."studentId" ASC

I get this data table :我得到这个数据表:

studentId | notation | givenHeart | total |      createdAt     |
----------+----------+------------+-------+--------------------+
 374      | 1        | 0          | 3     | 2017-02-13 12:43:03   
 374      | null     | 0          | 3     | 2017-02-15 22:22:17
 639      | 1        | 2          | 3     | 2017-04-03 17:21:30 
 790      | 1        | 0          | 3     | 2017-02-12 21:12:23
 ...

My goal is to keep only in my data table the early row of each group like shown below :我的目标是只在我的数据表中保留每个组的前一行,如下所示:

studentId | notation | givenHeart | total |      createdAt     |
----------+----------+------------+-------+--------------------+
 374      | 1        | 0          | 3     | 2017-02-13 12:43:03 
 639      | 1        | 2          | 3     | 2017-04-03 17:21:30 
 790      | 1        | 0          | 3     | 2017-02-12 21:12:23
 ...

How can I get there?我要怎么去那儿?

I've read many topics over here but nothing I've tried with DISTINCT , DISTINCT ON , subqueries in WHERE , LIMIT , etc have worked for me (surely due to my poor understanding).我在这里阅读了很多主题,但我没有尝试过DISTINCTDISTINCT ONWHERELIMIT子查询等对我有用(当然是由于我的理解不足)。 I've met errors related to window function, missing column in ORDER BY and a few others I can't remember.我遇到了与窗口函数相关的错误, ORDER BY缺少列以及其他一些我不记得的错误。

You can do this with distinct on .您可以使用distinct on做到这一点。 The query would look like this:查询将如下所示:

WITH responsesNew AS (
      SELECT DISTINCT r."studentId", notation, r."givenHeart", 
             SUM(notation + r."givenHeart") OVER (partition BY r."studentId" 
                                                  ORDER BY r."createdAt") AS total,
             r."createdAt" 
      FROM responses r
     )
SELECT DISTINCT ON (r."studentId") r."studentId", notation, r."givenHeart", total, 
r."createdAt"
FROM responsesNew r
WHERE total = 3
ORDER BY r."studentId" ASC, r."createdAt";

I'm pretty sure this can be simplified.我很确定这可以简化。 I just don't understand the purpose of the CTE.我只是不明白 CTE 的目的。 Using SELECT DISTINCT in this way is very curious.以这种方式使用SELECT DISTINCT非常奇怪。

If you want a simplified query, ask another question with sample data, desired results, and explanation of what you are doing and include the query or a link to this question.如果您想要一个简化的查询,请提出另一个问题,其中包含示例数据、所需结果以及您正在做什么的说明,并包括查询或此问题的链接。

use Row_number() window function to add a row number to each partition and then only show row 1.使用 Row_number() 窗口函数为每个分区添加一个行号,然后只显示第 1 行。

no need to fully qualify names if only one table is involved.如果只涉及一张表,则无需完全限定名称。 and use aliases when qualifying to simplify readability.并在限定时使用别名以简化可读性。

WITH responsesNew AS
(
  SELECT "studentId"
       , notation
       , "givenHeart"
       , SUM(notation + "givenHeart") OVER (partition BY "studentId" ORDER BY "createdAt") AS total
       , "createdAt"
       , Row_number() OVER ("studentId" ORDER BY "createdAt") As RNum
  FROM responses r
)
SELECT RN."studentId"
     , notation, RN."givenHeart"
     , total
     , RN."createdAt"
FROM responsesNew RN
WHERE total = 3
  AND RNum = 1
GROUP BY RN."studentId"
       , notation
       , RN."givenHeart", total
       , RN."createdAt"
ORDER BY RN."studentId" ASC

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

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