我有两个表:user
和 projects
,两者之间是一对多的关系。
projects
表包含包含用户项目状态的字段 status
。
status
可以是以下之一:
launched, confirm, staffed, overdue, complete, failed, ended
我想将用户分为两类:
- 有项目处于
launched
阶段的用户 - 用户的项目不是
launched
状态。
我正在使用以下查询:
SELECT DISTINCT(u.*), CASE
WHEN p.status = 'LAUNCHED' THEN 1
ELSE 2
END as user_category
FROM users u
LEFT JOIN projects p ON p.user_id = u.id
WHERE (LOWER(u.username) like '%%%'
OR LOWER(u.personal_intro) like '%%%'
OR LOWER(u.location) like '%%%'
OR u.account_status != 'DELETED'
AND system_role=10 AND u.account_status ='ACTIVE')
ORDER BY set_order, u.page_hits DESC
LIMIT 10
OFFSET 0
我面临以下情况的重复记录:
如果用户有状态为launched
以及overdue
、complete
或failed
的项目,则该用户记录两次,因为 CASE
中的两个条件都满足该用户。
请提出一个查询,其中有任何项目处于 launched
状态的用户将他的 user_category
设置为 1
。 user_category 2
不应重复同一用户。
最佳答案
由于多种原因,查询可能没有按照您的想法执行
有
DISTINCT
并且有DISTINCT
ON
(col1, col2)
。
DISTINCT (u.*)
与DISTINCT u.*
没有区别。括号只是杂音。AND
根据 operator precedence 在OR
之前绑定(bind).我怀疑您想在OR
的条件周围使用括号?或者你需要它的原样吗?但是在任何情况下都不需要将整个WHERE
子句括起来。您的表达式
LOWER(u.username) LIKE '%%%'
没有任何意义。每个非空字符串都符合条件。可以替换为u.username IS NOT NULL
。我怀疑你想要不同的东西?Postgres 在处理字符串时区分大小写。你写的
status
being 'launched' 等,但在你的查询中使用 'LAUNCHED'。是哪个?问题中缺少一些表格限定条件,使读者感到模棱两可。我按照我认为合适的方式填写。
一切都放在一起,它可能像这样工作:
SELECT DISTINCT ON (u.set_order, u.page_hits, u.id)
u.*
, CASE WHEN p.status = 'LAUNCHED' THEN 1 ELSE 2 END AS user_category
FROM users u
LEFT JOIN projects p ON p.user_id = u.id
WHERE LOWER(u.username) LIKE '%%%' -- ???
OR LOWER(u.personal_intro) LIKE '%%%'
OR LOWER(u.location) LIKE '%%%'
OR u.account_status != 'DELETED' -- with original logic
AND u.system_role = 10
AND u.account_status = 'ACTIVE'
ORDER BY u.set_order, u.page_hits DESC, u.id, user_category
LIMIT 10
这个相关问题的详细解释:
两个 EXISTS
semi-joins而不是 DISTINCT ON
和 CASE
可能会更快:
SELECT u.*
, CASE WHEN EXISTS (
SELECT FROM projects p
WHERE p.user_id = u.id AND p.status = 'LAUNCHED')
THEN 1 ELSE 2 END AS user_category
FROM users u
WHERE
( LOWER(u.username) LIKE '%%%' -- ???
OR LOWER(u.personal_intro) LIKE '%%%'
OR LOWER(u.location) LIKE '%%%'
OR u.account_status != 'DELETED' -- with alternative logic?
)
AND u.system_role = 10 -- assuming it comes from users ???
AND u.account_status = 'ACTIVE'
AND EXISTS (SELECT 1 FROM projects p WHERE p.user_id = u.id)
ORDER BY u.set_order, u.page_hits DESC
LIMIT 10;
关于sql - PostgreSQL 查询返回多行而不是一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13833434/