我已经读过这个question,但它并没有真正帮助我。 我有一个类似的房屋预订系统。因此,每当有人需要租房子时,他只需登录并选择他想要的房子是免费的时间,并预订。所以在我的情况下,我也有一个start_time和end_time。根据我的记录,我已经为每个日期准备了时间(日期时间格式),因此我可以根据时间精确度计算日期差异。以下是我的数据库示例:
CREATE TABLE IF NOT EXISTS `bookings` (
`id_booking` int(11) NOT NULL AUTO_INCREMENT,
`id_user_staff` int(11) NOT NULL,
`start_date` datetime NOT NULL,
`end_date` datetime NOT NULL,
`details` text,
`statut` varchar(45) DEFAULT NULL,
`id_house` int(1) NOT NULL,
`fees` decimal(6,0) DEFAULT NULL,
`ip_user` varchar(15) NOT NULL,
`date_booked` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id_booking`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `users` (
`id_user` int(5) NOT NULL DEFAULT '0',
`Last_Name` varchar(23) DEFAULT NULL,
`First_Name` varchar(23) DEFAULT NULL,
`Job_Title` varchar(56) DEFAULT NULL,
`Status` varchar(19) DEFAULT NULL,
`Company` varchar(38) DEFAULT NULL,
`Mobile` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id_user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `house` (
`id_house` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`details` text,
PRIMARY KEY (`id_house`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
我现在需要的是确定一年内房屋的占用率,根据房屋预订所包含的天数确定的精确度。该百分比是基于预订天数超过一年中天数的比率。 我的查询是什么,以获取天数并试图避免类似问题的问题,这些问题在某些日子计算两次?
答案 0 :(得分:1)
您可以使用DATEDIFF
,它可以显示两个日期之间的天数。但由于DATEDIFF('2015-01-01', '2015-01-01')
导致0天,因此您必须在结果中添加一天。
然后,总结每个房子的所有差异:
SELECT id_house, SUM(DATEDIFF(end_date, start_date) + 1)
FROM bookings
GROUP BY id_house
当然,从2015-01-01到2015-01-02以及从2015-01-02到2015-01-03预订的房子将导致三个预订日,因为一天预订两次。您可以在之后减去这些双重预订:
SELECT id_house, COUNT(*)
FROM bookings b1
WHERE (id_house, date(start_date)) IN
( SELECT id_house, date(end_date) FROM bookings AS b2 WHERE b1.id_booking <> b2.id_booking )
ORDER BY id_house
这会同时为您提供start_date和end_date(在两个不同的预订中)的天数。
最后,我会使用如下所示的查询,它总结了所有内容:
SELECT bookingdays.id_house, bookingdays.days, COALESCE(doublebookings.doubledays, 0), bookingdays.days - COALESCE(doublebookings.doubledays, 0) AS totaldays
FROM
(SELECT id_house, SUM(DATEDIFF(end_date, start_date) + 1) AS days
FROM bookings
GROUP BY id_house) bookingdays
LEFT OUTER JOIN
(SELECT id_house, COUNT(*) AS doubledays
FROM bookings b1
WHERE (id_house, date(start_date)) IN
( SELECT id_house, date(end_date) FROM bookings AS b2 WHERE b1.id_booking <> b2.id_booking )
ORDER BY id_house) doublebookings
ON bookingdays.id_house = doublebookings.id_house
答案 1 :(得分:0)
在报告域中使用日期的最佳方法是使用日期维度:
-- Source:
-- http://www.joyofdata.de/blog/setting-up-a-time-dimension-table-in-mysql/
SET @d0 = "2000-01-01";
SET @d1 = "2020-01-01";
SET @date = date_sub(@d0, interval 1 day);
# set up the time dimension table
DROP TABLE IF EXISTS date_dimension;
CREATE TABLE `date_dimension` (
`date` date DEFAULT NULL,
`id` int NOT NULL,
`y` smallint DEFAULT NULL,
PRIMARY KEY (`id`)
);
# populate the table with dates
INSERT INTO date_dimension
SELECT @date := date_add(@date, interval 1 day) as date,
# integer ID that allows immediate understanding
date_format(@date, "%Y%m%d") as id,
year(@date) as y
FROM T
WHERE date_add(@date, interval 1 day) <= @d1
ORDER BY date
;
获得日期维度表后,您可以加入预订并计算唯一日期。
每年的天数:
SELECT year, COUNT(*) FROM date_dimension GROUP BY YEAR;
每年和物业预订的天数:
SELECT year, house_id, COUNT(DISTINCT d.date)
FROM date_dimension d INNER JOIN bookings b
ON d.date BETWEEN b.start_date AND b.end_date
GROUP BY year, house_id
您可以修改第一个查询以成为子查询以获取百分比:
SELECT d.year, b.house_id,
COUNT(DISTINCT d.date) /
(SELECT COUNT(*)
FROM date_dimension WHERE year =d.year) AS annual_percent
FROM date_dimension d INNER JOIN bookings b
ON d.date BETWEEN b.start_date AND b.end_date
GROUP BY year, house_id
你会注意到,在你的工作中,如果使用日期维度,日期相关的计算将占用更少的SQL行,并使用更明确的语句。