繁体   English   中英

Mysql GROUP BY 和 Union 基于日期条件

[英]Mysql GROUP BY and Union based on date condition

这是我的查询 - 它主要工作,但我可以看到它在一个条件下失败 - 查询后解释:

$firstDay = '2020-03-01' ;
$lastDay = '2020-03-31' ;
SELECT * FROM clubEventsCal 
            WHERE ceFreq!=1
              AND (ceDate>='$firstDay' AND ceDate<='$lastDay') 
  UNION SELECT * FROM clubEventsCal 
            WHERE ceFreq=1
              AND (ceDate>='$firstDay' AND ceDate<='$lastDay') 
  GROUP BY ceStopDate ORDER BY ceID,ceDate ;

第一个 select 给了我两个日期之间的所有事件记录。 第二个 select 为我提供了两个日期之间的分组/汇总事件记录。 但问题是ceDate的值是否跨越两个月的天数:即:2020-03-30 到 2020-04-02。 当我提取 3 月的记录时,一切都很好 - 上述查询将 2020-03-30 记录(分组)作为 4 天/记录的第一个实例 - 允许我们为单个 4 天事件收费。 但是,当我提取 4 月的记录时,它也将2020-04-01作为 4 天活动的最后两天的新分组事件记录,并尝试向客户收取新事件的费用 - 实际上这两个天已经是三月账单的一部分。

如何编写查询,以便当 ceDate 在 X 月开始但在 Y 月结束时,当为 Y 月提取记录时,它不会尝试提取实际上属于在 X 月开始的事件的记录?

事件记录的示例如下所示:

rid | ceID  | ceActive   |   ceFreq   |  ceDate    | ceStopDate
------------------------------------------------
1    1108         1            3        2020-03-09 | 2020-03-09   
2    1111         1            2        2020-03-15 | 2020-03-15   
3    1112         1            2        2020-03-17 | 2020-03-17   
4    1117         1            1        2020-03-30 | 2020-04-02   
5    1117         1            1        2020-03-31 | 2020-04-02
6    1106         1            3        2020-03-21 | 2020-03-21   
7    1110         1            2        2020-03-05 | 2020-03-05   
8    1113         1            2        2020-03-24 | 2020-03-24   
9    1117         1            1        2020-04-01 | 2020-04-02
10   1117         1            1        2020-04-02 | 2020-04-02   

上面的查询提取ceFreq != 1的所有记录,并提取ceFreq = 1记录的单个记录(rids: 4 & 5)。 对于 3 月,我们不一定会关心 ceID 1117 会溢出到 4 月。 但是当我们提取 4 月份的记录时 - 我们需要排除第 9 和 10 条记录,因为事件 (ceID=1117) 已经在 3 月份计算在内。

SELECT * FROM clubEventsCal 
...
GROUP BY ceStopDate

这是胡言乱语。

MySQL(取决于配置)允许它不会窒息 - 但它在语义上是错误的并且作为反模式脱颖而出。

在某些极端情况下,返回的值可能包含重要数据,但它们非常不寻常。 试图用不起作用的代码解释问题可能不是一个好策略。

查看您的代码,您可能不需要联合 - 但您的示例记录中没有足够的信息来说明这是否真的会给出您期望的结果(根据您的索引,它会明显更快):

SELECT IF(cefreq=1, rid, null) AS consolidator
, ceid
, cefreq
, MIN(cedate), MAX(cedate)
, ceStopDate
FROM clubEventsCal 
WHERE cID=1001 
  AND ceActive!=2
  AND (ceDate>='$firstDay' AND ceDate<='$lastDay') 
GROUP BY IF(cefreq=1, rid, null)
, ceid
, cefreq
, ceStopDate
;

我会添加 ORDER BY - 但我不知道clId来自哪里。 此外,这将为我认为您试图为cefreq为 null 的任何记录提供不同的结果(如果您确实想排除它们,请在 WHERE 子句中添加一个谓词)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM