一、问题:
简单形象的比喻来说,比如,一斤苹果,在张三那卖,只有在表1的对应时间范围有卖,且对应的是价格1,然后在李四那卖,只有在表2的对应时间有卖,对应的是价格2,然后我想知道在李四有卖的时候,张三也有卖的情况下价格分别是多少?我想考虑哪个比较便宜,这里的时间就是包含关系。
*
二、分析
上面的问题就是对比价格的问题,表一存在就是zhangshan售卖表,表二存在就是李四的售卖情况表,两表售卖的东西都为同一种,表结构如下:
这时可以忽略货物的名称啥啥啥的,只用考虑zhangshan在售卖时间段内lisi是否在正常售卖,售卖就列出其价格和售卖时间
,lisi在售卖时间段zhangshan是否在售卖,如果在就对比价格,不在的话就列为空。
注意,此时两表存在的关联关系可以用笛卡尔积和以zhangsan表和lisi表为驱动查询对应的数据,再根据时间查询符合要求的数据!说干就干!
三、开始写加入测试数据,写sql
zhangsan表添加数据
INSERT INTO `shop_zhangsan`(`start_time`, `finish_time`, `current_price`, `id`) VALUES ('2022-09-04', '2022-09-09', 14.00, 1);
INSERT INTO `shop_zhangsan`(`start_time`, `finish_time`, `current_price`, `id`) VALUES ('2022-09-18', '2022-09-19', 15.00, 2);
lisi表添加数据
INSERT INTO `shop_lisi`(`id`, `start_time`, `finish_time`, `current_price`) VALUES (1, '2022-09-03', '2022-09-10', 12.00);
INSERT INTO `shop_lisi`(`id`, `start_time`, `finish_time`, `current_price`) VALUES (2, '2022-09-12', '2022-09-15', 13.00);
开始写sql !(此处sql写法有很多,我就使用最通俗易懂的来做了)
注:未考虑数据量大产生的join buffer问题
1、先使用二者笛卡尔交际来找对应符合条件的数据
SELECT
a.start_time AS lisi_st,
a.finish_time AS lisi_ft,
a.current_price AS lisi_cp,
b.start_time AS zhangshan_st,
b.finish_time AS zhangshan_ft,
b.current_price AS zhangshan_cp
FROM
shop_lisi a, shop_zhangsan b
where a.start_time < b.start_time AND a.finish_time > b.finish_time
or (a.start_time > b.start_time AND a.finish_time< b.finish_time)
结论 可以看出符合上述条件的数据就只有一条,不能直观的看出两者的售卖时间价格对比
2、使用关联查询筛选出对应条件的数据
常见的关联方式在mysql一般有三种,分别是join,left join,right join
还有两种分别取两表不相关的连接,有兴趣的小伙伴可以自行百度
a left join b on b.id is null
a right join b on a.id is null
我们此时想到的就是最简单的left join方式,以左表为驱动,查询关联数据,即是 a在售卖时间内b是否在售卖,价格如何,
同理,也可以以b表为驱动,查询a的情况(本人较懒,sql少改动就改成right join),两表取并集就是最终的数据了
下面是sql编写
SELECT
a.start_time AS lisi_st,
a.finish_time AS lisi_ft,
a.current_price AS lisi_cp,
b.start_time AS zhangshan_st,
b.finish_time AS zhangshan_ft,
b.current_price AS zhangshan_cp
FROM
shop_lisi a
LEFT JOIN shop_zhangsan b on
a.start_time < b.start_time AND a.finish_time > b.finish_time
UNION all
SELECT
a.start_time AS lisi_st,
a.finish_time AS lisi_ft,
a.current_price AS lisi_cp,
b.start_time AS zhangshan_st,
b.finish_time AS zhangshan_ft,
b.current_price AS zhangshan_cp
FROM
shop_lisi a
right JOIN shop_zhangsan b on
a.start_time > b.start_time AND a.finish_time < b.finish_time
这里采用的 union all 也可以换成union,union all没有对结果集去重,减少了回表的时间,因为上面的数据基本不存在重复数据,此处采用的union 关联两个查询的结果集也是可以的,效率影响不大。
最后看看结果吧:
上述结果满足最终的要求了,很清晰的对比(上述sql有很大的优化空间,感兴趣可以自己尝试一下)