【问题标题】:Counting with outer joins only returns data from which count is not zero使用外连接计数仅返回计数不为零的数据
【发布时间】:2019-02-08 02:54:48
【问题描述】:

假设我有两张桌子:userdiary

select count(id)
from user
where is_tester is false

这里的主键总是称为id。上面的这个查询给了我大约 270000,这意味着我有大约 270000 个用户。现在我想知道每个用户有多少日记。所以我去了:

select u.id as user_id, u.dm_type, count(d.id) as bg_count
from diary as d
right join (
    select id, dm_type
    from user
    where is_tester is false
) as u
on d.user_id = u.id
where d.glucose_value > 0
group by u.id, u.dm_type

每个用户只能拥有一种dm_type。我期待它会告诉我每个用户有多少日记,如果没有任何日记,它会给我一个 NA 或 0,因为我使用了right join。但是,返回的表只有大约 75000 行,并且该表中的每个用户至少有一本日记。那不是我想要的。为什么会发生,我应该如何正确处理?

我参考了Combining RIGHT JOIN with COUNT,并根据接受答案的建议统计了一个特定的字段。


根据 cmets 进行编辑:

user:

| id | dm_type | is_tester |
|----|---------|-----------|
| 1  | 1       | False     |
| 2  | 1       | False     |
| 3  | 2       | False     |
| 4  | no      | False     |
| 5  | 2       | True      |

diary:

| id | user_id | glucose_value |
|----|---------|---------------|
| 1  | 1       | -2            |
| 2  | 1       | 80            |
| 3  | 2       | 78            |
| 4  | 2       | 100           |
| 5  | 4       | 83            |
| 6  | 5       | 90            |

预期结果:

| user_id | dm_type | bg_count |
|---------|---------|----------|
| 1       | 1       | 1        |
| 2       | 1       | 2        |
| 3       | 2       | 0        |
| 4       | no      | 1        |

【问题讨论】:

  • 请分享表结构和所需的输出
  • @user2864740 right outer join 给了我完全相同的结果。顺便说一句,您似乎误解了我想要的输出。我想要HAVING COUNT(d.id) > 0INNER JOIN,因为我确实需要COUNT(d.id)的那些行是0。
  • @user2864740 对不起,我不明白你想说什么……我做了 right join,不是吗?根据您上面的评论,我尝试了right out join。那么它有什么问题呢?
  • @ytu,你能试试下面的答案吗,我希望它能解决你的问题
  • @codeLover 请查看我在问题中的编辑。

标签: sql postgresql count outer-join


【解决方案1】:

尝试左连接,它会给你所有用户是否有日记计数 如果任何用户没有日记,那么它会给你 null

select u.id as user_id, u.dm_type, count(d.id) as bg_count from
(select id, dm_type from user where is_tester is false)u
left join diary d on d.user_id = u.id and d.glucose_value > 0
group by u.id, u.dm_type

【讨论】:

  • 谢谢,但您的回答导致ERROR: missing FROM-clause entry for table "d"。应该是left join diary as d on d.user_id = u.id。但即使我相应地修改了你的答案,它仍然给我同一张桌子。
  • 编辑了答案..现在检查我错过了奶制品表的别名,您还需要在 on 子句中应用条件 d.glucose_value > 0。如果您应用它 where 子句,那么它将过滤掉结果。我希望现在它会帮助你
【解决方案2】:

您的查询的问题是where 子句。它正在从外部连接中过滤掉不匹配的日记。

当您遇到此类问题时,我强烈推荐left join 而不是right join。这意味着“保留第一个表中的所有行,即使第二个表中没有任何匹配项”。这通常比“保留 from 子句末尾的任何表中的所有行但我还没有看到”更容易理解。

下一个规则是 first 表上的条件放在where 子句中,因为它们确实过滤了行。第二个表的条件放在on 子句中。它们不过滤行,但用于匹配。

因此,您可以将查询表述为:

select u.id as user_id, u.dm_type, count(d.id) as bg_count
from user u left join
     diary d
     on d.user_id = u.id and d.glucose_value > 0
where u.is_tester is false
group by u.id, u.dm_type;

不需要子查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多