我似乎对SQL很无用,我正在试图弄清楚要使用的正确查询。
我有一个表项和一个表预订。一个项目可以有很多预订,并在两个日期之间进行预订。
我正在尝试创建一个搜索查询,该查询将返回两个用户输入日期之间没有预订的所有项目。
我现在的SQL看起来像:
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是什么。一个善良的灵魂能告诉我应该使用什么吗?
感谢
答案 0 :(得分:2)
如果某件事在两个日期之间有预订,则以下之一为真:
以下查询在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。
答案 1 :(得分:0)
你可以试试这个。
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
即将日期子句移动到WHERE子句中,而不是处于JOIN CLAUSE中
答案 2 :(得分:0)
我认为在CakePHP中你可能更容易将所有条件放在WHERE子句中。 (这也可以通过一些OUTER JOIN来完成,但可能很难转录到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
));