繁体   English   中英

SQL连接以获取不在两个日期之间的记录

[英]SQL join to get records that do not fall between two dates

我有以下表格:

discount table:
id
name
description
amount

discount_exception
id
from_date
to_date
discount_id (foreign key to discount table)

打折例外表用于存储日期范围,在该日期范围内,打折对用户不可用,因此不应显示。 请注意,折扣和discount_exception之间存在1:M关系。 换句话说,一种折扣可以有很多例外。

现在,我编写SQL的方式是获取所有折扣,然后在数组中循环浏览它们,并查询discount_exception表以找出每个折扣是否在特定日期范围内。 我希望修改SQL,以便一个数据库调用可以获取没有异常日期在指定日期范围内的所有折扣。

例如,如果用户购买的2013年5月1日至2013年5月5日至2013年5月5日之间运行的5天服务,我想查看Discount和Discount_exception表以找出哪些折扣具有2013-5年内的例外情况-1和2013-5-5,然后仅显示在指定日期范围内没有例外的折扣。 有没有一种方法可以使用一个select语句来执行此操作,而不是破坏SQL以针对每种折扣分别调用数据库? 我很难理解SQL,尤其是当折扣表和discount_exception表之间存在1:M关系时。

我正在尝试一些类似的方法:

SELECT * FROM discount INNER JOIN `discount_exceptions` ON discount.id = discount_exceptions.discount_id AND (discount_exceptions.date_from NOT BETWEEN '2013-5-1' AND '2013-5-5' OR discount_exception.date_to NOT BETWEEN '2013-5-1' AND '2013-5-5');

但是,这种方式和其他方式似乎无效。 知道我在做什么错吗?

谢谢!

如何尝试一下:


select * 
   from discount
    where id not in (
        SELECT discount.id FROM discount
LEFT JOIN discount_exception ON discount.id = discount_exception.discount_id WHERE ('2013-5-1' between discount_exception.from_date and discount_exception.to_date ) OR ('2013-5-5' BETWEEN discount_exception.from_date and discount_exception.to_date ) OR (discount_exception.from_date between '2013-5-1' and '2013-5-5' ) OR (discount_exception.to_date between '2013-5-1' and '2013-5-5') ) )
添加不重复以获得不重复ID可能更好

假设您要查找适用于日期范围“ 2013-03-01”至“ 2013-03-03”的所有折扣,首先要找到适用于该范围的所有discount_exceptions

select e.*
from discount_exception e 
where e.from_date between '2013-03-02' and '2013-03-04'
or e.to_date between '2013-03-02' and '2013-03-04';

在上方加入折扣表,将为您提供适用于该日期范围的所有折扣例外的折扣ID。 使用了不同的关键字,因此您不会得到重复的ID。 我们称其为“例外集”

select distinct d.id
from discount_exception e 
join discount d on d.id = e.discount_id
where e.from_date between '2013-03-02' and '2013-03-04'
or e.to_date between '2013-03-02' and '2013-03-04';

然后,您可以执行折扣表的另一个联接,以找到适用于日期范围的所有折扣(即ID不在上面设置的例外中的折扣)

select *
from discount
where id not in (
  select distinct d.id
  from discount_exception e 
  join discount d on d.id = e.discount_id
  where e.from_date between '2013-03-02' and '2013-03-04'
  or e.to_date between '2013-03-02' and '2013-03-04'
);

要检查交叉点,您只需要查看两个范围的起点是否在另一个范围内即可。 然后,您形成一个子查询以排除那些匹配的子查询。

set @start_date = CAST('2013-05-01' as date);
set @stop_date = CAST('2013-05-05' as date);

select *
from discounts
where id not in (select discount_id
                 from discount_exception
                 where from_date between @start_date and @stop_date or
                       @start_date between from_date and to_date)  

暂无
暂无

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

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