如果valid\u till为空,我想计算我的记录表的条目,通过valid\u from和valid\u till or按给定周期过滤

Records

id name valid_from valid_till
1 A 2022-07-01 2022-07-05
2 B 2022-07-02 2022-07-05
3 C 2022-07-02 2022-07-04
4 D 2022-07-03 null
5 E 2022-07-03 2022-07-03

现在,假设我从客户那里得到以下时间段(2022-06-30到2022-07-07).现在,我想找出与这个时间段匹配的所有记录,以及这个时间段中每个日期的点击数,而不仅仅是valid\u from和valid\u till.

我期望得到以下结果:

date matches
2022-06-30 0
2022-07-01 1
2022-07-02 3
2022-07-03 5
2022-07-04 4
2022-07-05 3
2022-07-06 0
2022-07-07 0

此外,我想通过了解当前用户已经读取了多少匹配项来扩展整个场景.为此,还有一个额外的表,用于保存每个用户和每个记录的信息.

Viewstates

id record user
1 1 X
2 1 Y
3 2 X
4 3 Y
5 4 X
6 4 Y
7 4 Z
8 5 X
9 5 Y
10 5 Z

假设我现在是用户X,那么我期望得到以下结果:

date matches already_read_by_me
2022-06-30 0 0
2022-07-01 1 1
2022-07-02 3 2
2022-07-03 5 4
2022-07-04 4 3
2022-07-05 3 3
2022-07-06 0 0
2022-07-07 0 0

不幸的是,我目前真的不知道如何实现和解决这个问题.

实际上,我的编码try 是这样的

SELECT
    COUNT(r.id) as matches,
    COUNT(vs.record_id) as already_ready_by_me
FROM
    records r
LEFT JOIN
    (
        SELECT id AS viewstate, record_id FROM viewstates WHERE user = 'xxx'
    ) vs ON r.id = vs.record_id
WHERE
    r.valid_from >= '2022-07-01'
    AND (r.valid_till <= '2022-07-10' OR r.valid_till IS NULL)
ORDER BY
    valid_from
DESC;

希望这里有人能帮助我.

谢谢.

BR,

推荐答案

您需要做的第一件事是像在selected_range子查询中那样连接输入日期.

在我的理解中,以下查询是正确的,因为如果一个记录有valid_till = null,这意味着它在NOW之前仍然有效,对吗?在你的例子中,2022-07-062022-07-07是匹配的,因为记录D在2022-07-03NOW之间有效

############## ONLY MATCHES
SELECT selected_range.date,
       COUNT(records.id) matches
FROM (        SELECT '2022-06-30' date
    UNION ALL SELECT '2022-07-01'
    UNION ALL SELECT '2022-07-02'
    UNION ALL SELECT '2022-07-03'
    UNION ALL SELECT '2022-07-04'
    UNION ALL SELECT '2022-07-05'
    UNION ALL SELECT '2022-07-06'
    UNION ALL SELECT '2022-07-07') selected_range
LEFT JOIN records ON selected_range.date BETWEEN records.valid_from 
                 AND COALESCE (records.valid_till, CAST(NOW() AS DATE))
GROUP BY selected_range.date        

############# MATCHES READ BY USER
SELECT selected_range.date,
       COUNT(records.id) matches,
       COUNT(viewstates.USER) already_read_by_me
FROM (        SELECT '2022-06-30' date
    UNION ALL SELECT '2022-07-01'
    UNION ALL SELECT '2022-07-02'
    UNION ALL SELECT '2022-07-03'
    UNION ALL SELECT '2022-07-04'
    UNION ALL SELECT '2022-07-05'
    UNION ALL SELECT '2022-07-06'
    UNION ALL SELECT '2022-07-07') selected_range
LEFT JOIN records ON selected_range.date BETWEEN records.valid_from 
                 AND COALESCE (records.valid_till, CAST(NOW() AS DATE))
LEFT JOIN viewstates ON viewstates.record = records.id 
                    AND viewstates.USER = 'X' 
GROUP BY selected_range.date

但是你的预期结果是可能的,然而我能够注意到的逻辑是,对于valid_till=null的记录是匹配的,必须有另一个有valid_till NOT null的记录.例如,对于2022-07-05,D记录匹配,因为记录A和B也匹配.

但对于2022-07-062022-07-07,没有考虑记录D,我理解这是因为没有其他匹配的记录.

所以我实现了这个逻辑:

######## ONLY MATCHES
SELECT selected_range.date,
       COUNT(records.id) matches
FROM (        SELECT '2022-06-30' date
    UNION ALL SELECT '2022-07-01'
    UNION ALL SELECT '2022-07-02'
    UNION ALL SELECT '2022-07-03'
    UNION ALL SELECT '2022-07-04'
    UNION ALL SELECT '2022-07-05'
    UNION ALL SELECT '2022-07-06'
    UNION ALL SELECT '2022-07-07') selected_range
LEFT JOIN records ON (selected_range.date BETWEEN records.valid_from 
                 AND COALESCE (records.valid_till, records.valid_from))
                 OR (EXISTS (SELECT 1 
                             FROM records records_inner
                             WHERE (selected_range.date BETWEEN records_inner.valid_from 
                                                        AND records_inner.valid_till)
                      AND selected_range.date >= records.valid_from
                      AND records.valid_till IS NULL
                 ))
GROUP BY selected_range.date 
                

######## MATCHES READ BY THE USER
SELECT selected_range.date,
       COUNT(records.id) matches,
       COUNT(viewstates.user) already_read_by_me
FROM (        SELECT '2022-06-30' date
    UNION ALL SELECT '2022-07-01'
    UNION ALL SELECT '2022-07-02'
    UNION ALL SELECT '2022-07-03'
    UNION ALL SELECT '2022-07-04'
    UNION ALL SELECT '2022-07-05'
    UNION ALL SELECT '2022-07-06'
    UNION ALL SELECT '2022-07-07') selected_range
LEFT JOIN records ON (selected_range.date BETWEEN records.valid_from 
                 AND COALESCE (records.valid_till, records.valid_from))
                 OR (EXISTS (SELECT 1 
                             FROM records records_inner
                             WHERE (selected_range.date BETWEEN records_inner.valid_from 
                                                        AND records_inner.valid_till)
                      AND selected_range.date >= records.valid_from
                      AND records.valid_till IS NULL
                 ))
LEFT JOIN viewstates ON viewstates.record = records.id 
                    AND viewstates.USER = 'X'
GROUP BY selected_range.date 

如果你觉得我的答案有用,请标记为接受并投票.

Mysql相关问答推荐

SQL查询仅插入5行

SQL MaxSum查询为列 Select 了不正确的值

Mysql,从两个不同的表中添加原始数据,从第一个表中获取所有内容,仅从第二个表中获取curdate内容

排序子查询结果并返回每个 ID 的第一行

Next-key lock explication - 范围的主键

如何查询由另一个查询创建的表?

在 Spring Data jpa 中的 @Query 中无法识别本机查询

判断一列中的多个值并返回值 1 或 0

由于长时间操作而断开连接后,我的 sql 查询是否继续执行?

使用 JOIN 计算列中的所有值

按 SQL 删除分组前的重复项

在 MySQL 中为多列创建索引以进行查询优化

我将如何构建一个 SQL 查询来从交易表中 Select 第一次存款、第二次存款和额外存款

mysql错误:错误1018(HY000):无法读取'.'的目录(错误号:13)

如何通过一个查询批量更新 mysql 数据?

计算执行的查询数

mysqli_fetch_array() 期望参数 1 为 mysqli_result,布尔值

如何使用 SQL 数据库中的经纬度查找最近的位置?

MySQL:切换 int 字段值的简单方法

如何允许 django 管理员将字段设置为 NULL?