这是我的查询--大部分情况下都能正常工作,但我可以看到它在一个条件上失败了--在查询后解释。
$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 ;
第一个选择给我两个日期之间的所有事件记录。 第二个选择给了我两个日期之间的分组汇总的事件记录。 但问题是如果值 ceDate
跨越两个月的天数。 即:2020-03-30至2020-04-02。 当我拉出3月的记录时,一切都很好--上述查询将2020-03-30记录(分组)作为4天记录的第一个实例拉出--允许我们为一个4天的活动收费。 但是,当我拉4月的记录,它也将拉动 2020-04-01
作为一个新的4天活动的最后两天的分组事件记录,并试图向客户收取一个新的事件--而事实上这两天已经是3月账单的一部分。
我如何编写查询,使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月份。 但是当我们拉出四月的记录时,我们需要排除rid 9 & 10,因为事件(ceID=1117),已经在三月被记录下来了。
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
来自。同时,这将给出不同的resuts,我认为你试图实现任何记录,其中 cefreq
是空的(如果你真的想排除它们,在WHERE子句中添加一个谓词)。