GROUP中真布尔值的SQLite Count()

zte4gxcn  于 2022-12-13  发布在  SQLite
关注(0)|答案(1)|浏览(153)

我想从视图中获取消息(它是一个视图,因为它包含来自多个源的消息)。如果有来自同一个用户的多个消息,我只想要最新的一个。视图已经按日期DESC排序。如果我使用查询SELECT *, COUNT(IsRead = false) FROM Messages GROUP BY User,我会得到每个用户的最新消息和每个用户的消息数量。但是,我只需要未读消息的数量,而不是消息的总数(Read == false)
对于下表:

+-------+--------+------------+
| User  | IsRead |    Date    |
+-------+--------+------------+
| User1 | false  | 2020-01-05 |
| User2 | false  | 2020-01-04 |
| User1 | false  | 2020-01-03 |
| User3 | true   | 2020-01-02 |
| User2 | true   | 2020-01-01 |
| User3 | true   | 2020-01-01 |
+-------+--------+------------+

我想得到以下结果

+-------+--------+------------+---------+
| User  | IsRead |    Date    | notRead |
+-------+--------+------------+---------+
| User1 | false  | 2020-01-05 |       2 |
| User2 | false  | 2020-01-04 |       1 |
| User3 | true   | 2020-01-02 |       0 |
+-------+--------+------------+---------+

我如何才能做到这一点?我的查询中的COUNT(IsRead = false)部分只是我想象中的工作方式。我在sqlite中找不到任何关于如何做到这一点的信息。
另外:如果视图的输出已经按日期降序排序,我关于总是从每个用户那里获得最新消息的说法是否正确?在我的测试中似乎是这样,但我只是想确保这不是侥幸。

pgx2nnw8

pgx2nnw81#

从SELECT/ORDER BY子句中:
如果返回多行的SELECT语句没有ORDER BY子句,则未定义行的返回顺序。
这意味着,即使视图被定义为返回排序行,从视图中进行选择也不能保证保持该排序顺序。
此外,使用此查询:

SELECT *, COUNT(IsRead = false) FROM Messages GROUP BY User

即使您 * 从每个用户 * 获得最新消息,这也保证,因为它不是文档中的功能。
所以,对于你的问题:
如果视图的输出已经按日期降序排序,我说的总是从每个用户那里获得最新的消息,对吗?
答案是否定的。
您不能依赖巧合的结果,但可以依赖记录的功能。
一个已记录的功能是在聚合查询中使用Bare列,它可以通过一个简单的聚合查询来解决您的问题:

SELECT User,
       IsRead,
       MAX(Date) Date,
       SUM(NOT IsRead) notRead -- sums all 0s (false) by converting them to 1s (true)
FROM Messages
GROUP BY User;

或者,使用窗口函数:

SELECT DISTINCT User,    
       FIRST_VALUE(IsRead) OVER (PARTITION BY User ORDER BY Date DESC) IsRead,
       Max(Date) OVER (PARTITION BY User) Date,
       SUM(NOT IsRead) OVER (PARTITION BY User) notRead 
FROM Messages;

请参阅demo

相关问题