sql - PostgreSQL 查询返回多行而不是一行

标签 sql postgresql greatest-n-per-group operator-precedence rails-postgresql

我有两个表:userprojects,两者之间是一对多的关系。
projects 表包含包含用户项目状态的字段 status

status 可以是以下之一:

launched, confirm, staffed, overdue, complete, failed, ended

我想将用户分为两类:

  1. 有项目处于launched阶段的用户
  2. 用户的项目不是 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 以及overduecompletefailed 的项目,则该用户记录两次,因为 CASE 中的两个条件都满足该用户。

请提出一个查询,其中有任何项目处于 launched 状态的用户将他的 user_category 设置为 1user_category 2 不应重复同一用户。

最佳答案

由于多种原因,查询可能没有按照您的想法执行

  • DISTINCT 并且有 DISTINCTON(col1, col2)
    DISTINCT (u.*)DISTINCT u.* 没有区别。括号只是杂音。

  • AND 根据 operator precedenceOR 之前绑定(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 ONCASE 可能会更快:

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/

相关文章:

sql - ORACLE 的 Postgres 转换 KEEP DENSE_RANK FIRST

php - MySQL 唯一键场景

java - Postgres 中的生成值

mysql - GROUP BY 中的 ORDER BY 和 LIMIT

PostgreSQL - 如何在例程中对 null 使用 equals

postgresql - 如何在 GCP 的 PostgreSQL 中安装外部扩展

php - 每个论坛最新帖子的 MySQL 查询设计

Mysql 查询 - 从 CSV 条件插入到表和 CSV 之间的比较

sql - 使用 MySQL 作为键/值数据库的可扩展性

java - 找不到 DataSource.getConnection()