【问题标题】:To check a date in one table does NOT exist in reservation period in 2nd table检查一个表中的日期在第二个表的保留期内不存在
【发布时间】:2011-12-21 12:48:40
【问题描述】:


在花了 2 天时间试图在网上找到答案后,我对此很陌生 我正在尝试构建一个 MYSQL 选择语句

我在 e 上有 2 个包含日期和价格列表的表,第二个是包含开始和结束的预订日期表。我试图在表 1 中显示所有在表 2 中的任何预订记录中都不存在的免费日期和价格

表 1 调用 - dates_prices -
ID、日期、价格

示例数据

333, 2011-12-20, 66.00
333, 2011-12-21, 66.00
333, 2011-12-22, 66.00
333, 2011-12-23, 66.00
333, 2011-12-24, 66.00
333, 2011-12-25, 66.00
333, 2011-12-26, 66.00
333, 2011-12-27, 66.00
333, 2011-12-28, 66.00
333, 2011-12-29, 66.00
333, 2011-12-30, 66.00

表 2 - 保留

id、开始日期、结束日期

示例数据

333, 2011-12-20, 2011-12-22
333, 2011-12-24, 2011-12-26
333, 2011-12-28, 2011-12-30

我只需要从表 1 中提取不存在于表 2 记录中的日期,这些日期在表 2 中具有相同 ID 号 333 的所有记录的开始日期和结束日期之间

所以应该从表 1 中显示的唯一记录如下

id、日期、价格

333, 2011-12-23, 66.00
333, 2011-12-27, 66.00
333, 2011-12-31, 66.00

【问题讨论】:

  • 您忘记了 dates_prices 中的条目“333, 2011-12-30, 66.00”。

标签: mysql not-exists


【解决方案1】:
SELECT p1.* FROM dates_prices p1 
WHERE (p1.id, p1.date) NOT IN
(
  SELECT p2.id, p2.date
  FROM dates_prices p2
  JOIN reservations r
  ON  (
     r.id = p2.id 
     and r.startdate <= p2.date 
     and p2.date <= r.enddate
  )
)

【讨论】:

  • 此查询由于某种原因未返回 12-29 条目
  • @BrianHoover 它不应该:12-29 介于 12-28 和 12-30 afaik
  • 是的,我刚刚再次阅读了要求。但是它没有返回 12/31 条目。
  • 我运行了 Brian 提供的上一个版本 - 非常快,但无法处理预订表中的多个范围 - 带有 JOIN 的版本非常占用 cpu 需要 2 分钟才能完成 - 我的表有 80,000 dates_prices 中的条目,我的预订有 850 个条目
  • 已编辑:我忘记了 p1.id。你能再试试这个吗?也许 dates_prices(id, date) 上的索引会有所帮助。
【解决方案2】:

我已更新查询以排除日期。

select dp.id, dp.date, dp.price
  from dates_prices dp
   left join 
     (select dp.id, dp.date
       from dates_prices dp
       join reservations res 
        on res.id = dp.id 
         and dp.date between res.startdate and res.enddate) as inner_table
     on inner_table.id = dp.id and inner_table.date = dp.date
   where inner_table.id is null 

【讨论】:

  • @greyfairer - 我刚刚在我的机器上重建了他的表格和数据,它运行良好。
【解决方案3】:
create table  table12 (id int, datefor date, price int)

insert  into  table12
select 333, '2011-12-20', 66.00
union all
select 333, '2011-12-21', 66.00
union all
 select 333, '2011-12-22', 66.00
 union all
 select 333, '2011-12-23', 66.00
 union all
select 333, '2011-12-24', 66.00
union all
 select 333, '2011-12-25', 66.00
 union all
 select 333, '2011-12-26', 66.00
 union all
 select 333, '2011-12-27', 66.00
 union all
 select 333, '2011-12-28', 66.00
 union all
 select 333, '2011-12-29', 66.00
 union all
 select 333, '2011-12-30', 66.00 

 create table  table2 (id int, startdate date, enddate date)

insert  into  table2
select 333, '2011-12-20', '2011-12-22'
 union all
 select 333, '2011-12-24', '2011-12-26'
 union all
 select 333, '2011-12-28', '2011-12-30'

在创建上述表格后尝试此操作。你的问题的解决方案是你需要对表进行这种类型的查询,即 select * from table12 where datefor not between '2011-12-20' and '2011-12-22' and datefor not between '2011-12-24' and '2011-12-26' and datefor not between '2011-12' -28' 和 '2011-12-30' 和 table12.id=333 我做了一个 proc 只是你需要传递你的 id。

create proc solution( @id int) 
  as
  begin

declare @count int
    declare @i int
    declare @query varchar(800)
    set @query=''
 declare @startdate varchar(80)
    set @startdate=''
     declare @enddate varchar(80)
    set @enddate=''

 declare @table table( row int ,startdate date,enddate date,id int)
insert into @table select row_number() over(order by (select 1)) as rownumber  ,startdate,enddate,id  from  table2  where table2.id=@id
 set  @count=(select COUNT (*)  from  @table )
 set   @i=1
 set @query += 'select * from  table12 where '
while @count>=@i
begin
 set @startdate=( select startdate  from  @table  where row=@i) 
 set  @enddate =(select enddate  from  @table  where row=@i)
 set @query +=  ' datefor not between '+''''+@startdate+''''+ ' and '+'''' +@enddate+''''
 if   @count>@i
 begin
 set @query +=' and  '
 end
 if @count=@i
 begin
 set @query += ' and  table12.id='+cast (@id as varchar(50)) +''
 end 

set @i+=1
 end
 if(@i=1)
 set @query+='table12.id='+cast (@id as varchar(50)) +''


  exec (@query)
end

exec solution 333

【讨论】:

    【解决方案4】:

    这应该也可以,可能会快很多:

    SELECT p1.* FROM dates_prices p1 
    WHERE NOT EXISTS
    (
      SELECT * FROM reservations r
      WHERE r.id = p1.id 
      AND r.startdate <= p1.date 
      AND p1.date <= r.enddate  
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-05
      • 2013-07-23
      • 1970-01-01
      • 2020-11-13
      • 2020-05-17
      • 2020-11-13
      • 2023-03-29
      • 2015-10-26
      相关资源
      最近更新 更多