根据另一个 table 的日志时间减去或添加数据

Subtracting or Adding data based on logtime of another table

所以目前我有 2 个 table 称为列表和日志 table。列表 table 包含产品参考编号及其当前状态。因此,假设如果它的状态是当前发布并且已售出,则状态更新为已售出。这里是 refno。其中 table 是唯一的,因为 1 个产品的状态可以更改。

现在我有另一个 table 称为日志 table,这个 table 记录了特定产品(由 refno 引用)在特定时间范围内发生的所有状态更改。假设带有 refno 的产品。 5 于 10 月 1 日发布并于 10 月 2 日售出,日志 table 将显示为:

Refno status_from status_to logtime
5 Stock Publish 2021-10-01
5 Publish Sold 2021-10-02

这是我的 table 目前的样子:

列表table:('D'=>'Draft','N'=>'Action','Y'=>'Publish')

Logs Table 我正在使用以下语句:

SELECT refno, logtime, status_from, status_to FROM ( 
SELECT refno, logtime, status_from, status_to, ROW_NUMBER() OVER(PARTITION BY refno ORDER BY logtime DESC)
AS RN FROM crm_logs WHERE logtime < '2021-10-12 00:00:00' ) r 
WHERE r.RN = 1 UNION SELECT refno, logtime, status_from, status_to
FROM crm_logs WHERE logtime <= '2021-10-12 00:00:00' AND logtime >= '2015-10-02 00:00:00'
ORDER BY `refno` ASC

日志 table 对每个状态更改进行新记录,并将当前时间戳作为日志时间传递,列表 table changes/updates 状态并更新其 update_date.现在要获取截至今天的总列表,我使用以下语句:

SELECT SUM(status_to = 'D') AS draft, SUM(status_to = 'N') AS action, SUM(status_to = 'Y') AS publish FROM `crm_listings`

这 returns 截至当天状态的所有计数数据。

这就是让我感到困惑的地方。因此,假设今天正在执行的计数是 10,明天将是 15,我想检索昨天出现的总数 (10)。因此,为此我要做的是取今天的总数 (15) 并减去昨天和今天之间产品更改为草稿的所有地方(今天列表中的总计数 table - count(*)其中 status_to='Action' 来自日志 table)。反之亦然,如果昨天它是 10,今天它是 5,它应该添加日志 table

中 status_from 列的值

注意:Refno 在我的日志中不是唯一的 table 因为具有相同 refno 的产品可以标记为发布 1 天并取消发布另一天,但它在我的列表中是独一无二的 table.

Link 到 dbfiddle:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=01cb3ccfda09f6ddbbbaf02ec92ca894

我相信它可以被简化或变得更好。但这是我的查询和逻辑:

  1. 我发现每个 refno 的 status_changes 并计算了从所需日期到现在的总变化:

select status_logs, sum(cnt_status) to_add from (
SELECT 
status_to as status_logs, -1*count(*) cnt_status
FROM logs lm
where
id = (select max(id) from logs l where l.refno = lm.refno) and 
logtime >= '2021-10-01 00:00:00'
group by status_to
union all 
SELECT 
status_from, count(*) cnt_status_from
FROM logs lm
where
id = (select max(id) from logs l where l.refno = lm.refno) and
logtime >= '2021-10-01 00:00:00'
group by status_from ) total_changes
group by status_logs

  1. 我通过转换列表 table 键来匹配列表 table 和日志 table 之间的键:

select
case status
when 'D' THEN 'Draft'
when 'A' THEN 'Action'
when 'Y' THEN 'Publish'
when 'S' THEN 'Sold'
when 'N' THEN 'Let'
END status_l ,COUNT(*) c
from listings
group by status

  1. 我加入了他们并将计算添加到当前数据的总和中。

  1. 我不得不使用完全外连接,所以我有一个左连接和一个右连接与相同的子查询。

最后我使用了 distinct ,因为它会为每个连接的查询生成相同的结果,并使用 ifnull 将其他 tables 状态带到另一列。

select distinct IFNULL(status_l, status_logs) status, counts_at_2021_10_01
  from (select l.*,
               logs.*,
               l.c + ifnull(logs.to_add, 0) counts_at_2021_10_01
          from (select case status
                         when 'D' THEN
                          'Draft'
                         when 'A' THEN
                          'Action'
                         when 'Y' THEN
                          'Publish'
                         when 'S' THEN
                          'Sold'
                         when 'N' THEN
                          'Let'
                       END status_l,
                       COUNT(*) c
                  from listings
                 group by status) l
          left join (
                    
                    select status_logs, sum(cnt_status) to_add
                      from (SELECT status_to as status_logs,
                                    -1 * count(*) cnt_status
                               FROM logs lm
                              where id = (select max(id)
                                            from logs l
                                           where l.refno = lm.refno)
                                and logtime >= '2021-10-01 00:00:00'
                              group by status_to
                             union all
                             SELECT status_from, count(*) cnt_status_from
                               FROM logs lm
                              where id = (select max(id)
                                            from logs l
                                           where l.refno = lm.refno)
                                and logtime >= '2021-10-01 00:00:00'
                              group by status_from) total_changes
                     group by status_logs) logs
            on logs.status_logs = l.status_l
        union all
        select l.*,
               logs.*,
               l.c + ifnull(logs.to_add, 0) counts_at_2021_05_01
          from (select case status
                         when 'D' THEN
                          'Draft'
                         when 'A' THEN
                          'Action'
                         when 'Y' THEN
                          'Publish'
                         when 'S' THEN
                          'Sold'
                         when 'N' THEN
                          'Let'
                       END status_l,
                       COUNT(*) c
                  from listings
                 group by status) l
         right join (
                    
                    select status_logs, sum(cnt_status) to_add
                      from (SELECT status_to as status_logs,
                                    -1 * count(*) cnt_status
                               FROM logs lm
                              where id = (select max(id)
                                            from logs l
                                           where l.refno = lm.refno)
                                and logtime >= '2021-10-01 00:00:00'
                              group by status_to
                             union all
                             SELECT status_from, count(*) cnt_status_from
                               FROM logs lm
                              where id = (select max(id)
                                            from logs l
                                           where l.refno = lm.refno)
                                and logtime >= '2021-10-01 00:00:00'
                              group by status_from) total_changes
                     group by status_logs) logs
            on logs.status_logs = l.status_l) l