我有一个具有以下结构(近似)的表rate

CREATE TABLE `rate` (
    `id`       int(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
    `from`     date NOT NULL,
    `to`       date NOT NULL
)


和一个(大约)相同的表stop_sale

CREATE TABLE `stop_sale` (
    `id`       int(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
    `from`     date NOT NULL,
    `to`       date NOT NULL
)


考虑到每个时间间隔是它们各自的fromto字段之间覆盖的天数范围:

我想以时间间隔不重叠的方式一起查询这些表,而是调整以使stop_sale优先。



rates

| id | from         | to           |
| 1  | "2018-01-05" | "2018-01-31" |
| 2  | "2018-02-01" | "2018-02-15" |


stop_sale

| id | from         | to           |
| 1  | "2018-01-11" | "2018-01-20" |
| 2  | "2018-02-01" | "2018-02-10" |


所需结果

| rate_id | from         | to           |
| 1       | "2018-01-05" | "2018-01-10" |
| 0       | "2018-01-11" | "2018-01-20" |
| 1       | "2018-01-21" | "2018-01-31" |
| 0       | "2018-02-01" | "2018-02-10" |
| 2       | "2018-02-11" | "2018-02-15" |


注意,带有rateid=1如何基于带有stop_rateid=1的时间间隔分为两个记录(注意:id并不重要,只是时间间隔)。

换句话说,stop_sale时间间隔在rate时间间隔上执行减法运算,并且还涂有最终结果集。


SQL可能吗?和MySQL?
如果是这样,查询的最佳状态是什么?用PHP处理此操作是否更好?

最佳答案

据我所知,仅凭SQL查询是无法做到这一点的。可以在存储的函数中迭代解决此问题,但是没有干净的方法可以返回数据。最好是返回一个带分隔符的数据字符串。

一种替代方法是构建一个存储过程,该存储过程定期填充结果数据表,并对其进行php查询。基本逻辑是:

传递起始数据值-起始日期。

用查询创建一个临时表:

    select * from rates
    where from >= starting_date
    union
    select * from stop_sale
    where from >= starting_date
    order by from asc



遍历临时表。


获得第一个“来自”价值。
获得更大的“价值”价值
查找'from'值当前'from'值,但!='from'值已在正在填充的结果表中


如果找到,则将当前的“从”值和“至”值-1天插入到要填充的结果表中
否则将当前的“从”值和“到”值插入到要填充的结果表中




这种基本逻辑可以在php中完成,尽管它可能更复杂,因为您将需要构建一个从上述临时表查询返回的行的数组,在其上运行该逻辑,并构建一个结果数组。这将比运行存储过程效率低,因为一旦运行存储过程,您将只需要在比该运行过程更新的数据上再次运行该存储过程。因此,starting_data参数。

希望对您有帮助。

关于mysql - 用其他日期分割日期,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48117311/

10-12 07:34