简体   繁体   中英

Postgresql select distinct Column A based on certain conditions on Column B

I have a table with data:

+--------+---------+
| userid | status  |
+--------+---------+
| user_1 | success |
| user_2 | fail    |
| user_2 | success |
| user_3 | fail    |
| user_3 | fail    |
+--------+---------+

I would like my query output to be distinct on userid but with condition that between fail and success values in status column. I would like to choose success instead (if both fail as in user_3 , choose fail then). The table below shows the output that I would like to have as my result:

+--------+---------+
| userid | status  |
+--------+---------+
| user_1 | success |
| user_2 | success |
| user_3 | fail    |
+--------+---------+

Any efficient query would be nice as well. Thanks!

Here is a pretty efficient way to get the results you need.

SELECT userid, MAX(status)
FROM table1
GROUP BY userid

The MAX() function will work for strings as well. Since, "success" > "fail", if a userid has 1 row of "success" and 1 row of "fail", the maximum value is "success"

Use SELECT DISTINCT ON , which provides a simple and readable method to get the rows unique on userid . The ORDER BY ensures that status = 'success' is sorted before 'fail' , and hence 'success' is selected if present:

SELECT DISTINCT ON (userid) userid,
                   status
FROM my_table
ORDER BY userid,
         status DESC;

Note: An multicolumn index on (status, userid) may help performance. Also, in some cases a query using GROUP BY (see the answer from Terence) may be faster than the one using DISTINCT .


SELECT DISTINCT ON ( expression [, ...] ) keeps only the first row of each set of rows where the given expressions evaluate to equal. ... The DISTINCT ON expression(s) must match the leftmost ORDER BY expression(s). The ORDER BY clause will normally contain additional expression(s) that determine the desired precedence of rows within each DISTINCT ON group.

(From SELECT DISTINCT docs )

First select status is success userid.

select distinct  userid,status from yourtable where status='success'

Second select userid not contain success status.

select distinct  userid,status from yourtable where 
userid not in(select distinct userid from yourtable where status='success')

Then union.

select distinct  userid,status from yourtable where status='success'
union
select distinct  userid,status from yourtable where 
userid not in(select distinct userid from yourtable where status='success')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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