我有两张表: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
,那么该用户将被记录两次{{1这个用户满意。
请建议一个查询,其中具有CASE
状态的任何项目的用户将其launched
设置为user_category
。 1
不应重复使用同一个用户。
答案 0 :(得分:3)
由于多种原因,查询可能没有按照您的想法进行操作
DISTINCT
有DISCTINCT
ON
(col1, col2)
。
DISTINCT (u.*)
与DISTINCT u.*
没有区别。括号只是噪音。
AND
根据operator precedence在OR
之前绑定。我怀疑你想在条件OR一起使用括号吗?或者你是否需要它的方式?但是在任何情况下,你都不需要围绕整个WHERE
子句使用括号。
您的表达式LOWER(u.username) LIKE '%%%'
没有任何意义。每个非空字符串都符合条件。可以用u.username IS NOT NULL
替换。我怀疑你想要不同的东西?
PostgreSQL在字符串处理中区分大小写。您写的是status
被'启动'等,但在查询中使用'已启动'。它会是什么?
问题中缺少一些表格资格,使读者感到含糊不清。我用锯子填写。
所有东西放在一起可能就像这样工作:
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 1 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;
答案 1 :(得分:1)
您可以在MIN()
结果上使用CASE
,似乎放弃DISTINCT将是明智的选择:
SELECT u.*, MIN(CASE
WHEN p.status = 'LAUNCHED' THEN 1
ELSE 2
END) as user_category
...
GROUP BY <list all columns in the users table>
...
由于“已启动”给出1,因此使用MIN()不仅会强制执行单个结果,还会优先于其他状态“启动”。