mysql查询-如何查找不在特定日期内的项目
我似乎对SQL一窍不通,我正试图找出应该使用的正确查询 我有一张桌子项目和一张桌子预定。一个项目可以有许多预订,并且预订是在两个日期之间进行的 我正在尝试创建一个搜索查询,它将返回在两个用户输入日期之间没有预订的所有项目 我目前拥有的SQL如下所示:mysql查询-如何查找不在特定日期内的项目,mysql,sql,cakephp,Mysql,Sql,Cakephp,我似乎对SQL一窍不通,我正试图找出应该使用的正确查询 我有一张桌子项目和一张桌子预定。一个项目可以有许多预订,并且预订是在两个日期之间进行的 我正在尝试创建一个搜索查询,它将返回在两个用户输入日期之间没有预订的所有项目 我目前拥有的SQL如下所示: SELECT `Item`.`id`, `Item`.`user_id`, `Item`.`name`, `Item`.`description`, `User`.`id`, `User`.`username`, `User`.`password`
SELECT `Item`.`id`, `Item`.`user_id`, `Item`.`name`, `Item`.`description`, `User`.`id`, `User`.`username`, `User`.`password`, `User`.`email`
FROM `database`.`items` AS `Item`
LEFT JOIN `database`.`reservations` AS `ReservationJoin` ON (`ReservationJoin`.`item_id` = `Item`.`id` AND `ReservationJoin`.`start` >= '2013-07-17' and `ReservationJoin`.`finnish` <= '2013-07-20')
LEFT JOIN `database`.`users` AS `User` ON (`Item`.`user_id` = `User`.`id`)
WHERE ((`Item`.`name` LIKE '%projector%') OR (`Item`.`description` LIKE '%projector%')
AND `ReservationJoin`.`id` IS NULL
LIMIT 10
我在cakephp 2.3中执行此操作,因此代码如下所示:
$this->paginate = array(
"conditions" => array(
"or" => array(
"Item.name LIKE" => '%'.$projector.'%',
"Item.description LIKE" => '%'.$projector.'%',
),
"ReservationJoin.id" => null,
),
"joins" => array(
array(
"table" => "reservations",
"alias" => "ReservationJoin",
"type" => "LEFT",
"conditions" => array(
"ReservationJoin.item_id = Item.id",
"ReservationJoin.checkin >= '{$start}' and ReservationJoin.checkout <= '{$finnish}'",
)
)
),
"limit"=>10
);
$data = $this->paginate('Item');
这不起作用,我认为这与加入有关,而不是正确地排除预订。但是我还没有弄清楚什么是正确的mysql。善良的灵魂能告诉我应该用什么吗
谢谢如果某物在两个日期之间有预订,则以下情况之一是正确的: 两个日期之间有一个开始日期 两个日期之间有一个结束日期 它的开始日期在较早的日期之前,结束日期在第二个日期之后 以下查询在having子句中使用此逻辑。该方法是在项目级别进行汇总,并确保上述三个条件为真:
SELECT i.`id`, i.`user_id`, i.`name`, i.`description`
FROM `database`.`items`i LEFT JOIN
`database`.`reservations` r
ON r.`item_id` = i.`id`
WHERE ((i.`name` LIKE '%projector%') OR (i.`description` LIKE '%projector%')
group by i.id
having max(start between '2013-07-17' and '2013-07-20') = 0 and
max(finish between '2013-07-17' and '2013-07-20') = 0 and
max(start < '2013-07-17' and finished > '2013-07-20') = 0
LIMIT 10;
请注意,不会返回任何匹配项,因为当start和ned为NULL时,条件将被视为false。您可以尝试此操作
SELECT `Item`.`id`, `Item`.`user_id`, `Item`.`name`, `Item`.`description`, `User`.`id`, `User`.`username`, `User`.`password`, `User`.`email`
FROM `database`.`items` AS `Item`
LEFT JOIN `database`.`reservations` AS `ReservationJoin` ON (`ReservationJoin`.`item_id` = `Item`.`id`)
LEFT JOIN `database`.`users` AS `User` ON (`Item`.`user_id` = `User`.`id`)
WHERE ((`Item`.`name` LIKE '%projector%') OR (`Item`.`description` LIKE '%projector%'))
AND `ReservationJoin`.`start` >= '2013-07-17'
AND `ReservationJoin`.`finnish` <= '2013-07-20'
AND `ReservationJoin`.`id` IS NULL
LIMIT 10
i、 只需将date子句移到WHERE子句,而不是JOIN子句我认为在CakePHP中,将所有条件都放在WHERE子句中可能更容易。这也可以通过一些外部连接来完成,但可能很难转录成CakePHP
SELECT id, user_id, name, description
FROM items
WHERE ((name LIKE '%projector%') OR (description LIKE '%projector%'))
AND NOT EXISTS(
SELECT *
FROM reservations
WHERE items.id = reservations.item_id
AND (
'2013-07-17' BETWEEN start and finnish
OR
'2013-07-20' BETWEEN start and finnish
OR
start BETWEEN '2013-07-17' AND '2013-07-20'));
或者,使用相同的逻辑,可以将WHERE子句清理为
SELECT id, user_id, name, description
FROM items
WHERE ((name LIKE '%projector%') OR (description LIKE '%projector%'))
AND NOT EXISTS(
SELECT *
FROM reservations
WHERE items.id = reservations.item_id
AND NOT(
'2013-07-17' > finnish
OR
'2013-07-20' < start
));
嗨,戈登,谢谢你的回复。不幸的是,使用GROUPBY子句显然破坏了cakephp中的分页。还有其他方法吗?谢谢你的回复。我喜欢这个想法,因为它看起来最容易翻译成cakephp。所以我成功地做到了这一点,生成的SQL正如您所建议的那样。但无论使用什么日期或不使用任何日期,都不会返回任何结果。知道会发生什么吗?知道如何在cakephp中为paginate调用设置它吗?我正在努力为自己找到答案。我想我终于找到了如何将你的答案转换成cakephp的方法,看起来效果不错:快乐发呆。谢谢