包含复杂查询 date_format 和之间
Contain complex query date_format and between
Code Update 2017/07/20
我按照@Arcesilas (here) 的建议使用了 MySQL 的 date_format
。
我通过合并 start_month
和 start_day
(ex 2017-01-16 = 0116)
升级了我的数据结构
[...]
->contain([
'Bookings',
'Amenities',
'Periodicities' => function ($q) use ($check_in, $check_out) {
$start = $q->func()->date_format([
'Periodicities.start' => $check_in->format('Ymd'),
"'%m%d'" => 'literal'
]);
$end = $q->func()->date_format([
'Periodicities.end' => $check_out->format('Ymd'),
"'%m%d'" => 'literal'
]);
return $q
->where(function ($exp) use ($start) {
$exp->between($start, 'Periodicities.start', 'Periodicities.end');
return $exp;
})
->orWhere(function ($exp) use ($end) {
$exp->between($end, 'Periodicities.start', 'Periodicities.end');
return $exp;
});
}
])
[...]
CakephpSQL日志
SELECT
PeriodicitiesRooms.id AS `Periodicities_CJoin__id`,
PeriodicitiesRooms.periodicity_id AS `Periodicities_CJoin__periodicity_id`,
PeriodicitiesRooms.room_id AS `Periodicities_CJoin__room_id`,
PeriodicitiesRooms.price AS `Periodicities_CJoin__price`,
Periodicities.id AS `Periodicities__id`,
Periodicities.name AS `Periodicities__name`,
Periodicities.start AS `Periodicities__start`,
Periodicities.end AS `Periodicities__end`,
Periodicities.price AS `Periodicities__price`,
Periodicities.modified AS `Periodicities__modified`
FROM
periodicities Periodicities
INNER JOIN periodicities_rooms PeriodicitiesRooms ON Periodicities.id = (
PeriodicitiesRooms.periodicity_id
)
WHERE
(
date_format('20170726', '%m%d') BETWEEN 'Periodicities.start'
AND 'Periodicities.end'
OR (
PeriodicitiesRooms.room_id in ('1', '2', '3')
AND date_format('20170720', '%m%d') BETWEEN 'Periodicities.start'
AND 'Periodicities.end'
)
)
这不会再给我任何结果,因为 CakePHP 的 ORM 在 BETWEEN' Periodicities.start 'AND' Periodicities.end'
的末尾添加了撇号 (')
如果我在我的数据库中粘贴不带撇号 (') 的 CakePHP 查询,它会起作用。您是否知道要对我的查询末尾进行哪些更改,使其看起来像这样:BETWEEN 'Periodicities.start' AND 'Periodicities.end'
到 BETWEEN Periodicities.start AND Periodicities.end
?
'SELECT * FROM periodicities WHERE date_format(' . $check_in->format('Ymd') . ', '%m%d') BETWEEN start AND end'
编辑
从您的评论中我看到您不想存储年份,因为年份不相关。
在这种情况下,您仍然可以将所有日期存储为特定年份,然后将该年份硬编码到查询中。我已将查询修改为使用 2000 年。
原版
我不清楚对话内容,但我会尝试回答您提出的问题。
您似乎想知道如何查找签入时间之间的 Periodicities 或结帐时间之间的 Periodicities。
您似乎还想知道存储日期的最佳方式。
- 只需将日期存储为日期。没必要搞复杂
Between
也太复杂了。
这将完成您需要它做的事情而不会造成混淆。
[...]
->contain([
'Bookings',
'Amenities',
'Periodicities' => function ($q) use ($check_in, $check_out) {
$q->where([
'Periodicities.start >' => $check_in->format('2000-m-d'),
'Periodicities.end <' => $check_in->format('2000-m-d')
]);
$q->orWhere([
'Periodicities.start >' => $check_out->format('2000-m-d'),
'Periodicities.end <' => $check_out->format('2000-m-d')
]);
return $q;
}
])
[...]
我用这个查询解决了我的问题:
->contain([
'Bookings',
'Amenities',
'Periodicities' => function ($q) use ($check_in, $check_out) {
$q->where(function ($exp) use ($check_in, $check_out) {
$exp->gte('Periodicities.start', $check_in->format('md'));
$exp->lte('Periodicities.end', $check_out->format('md'));
});
return $q;
}
])
我一直以 month
和 day
md
格式在数据库中存储日期
例如:0901 < 1030
9 月 1 日 < 10 月 30 日
Code Update 2017/07/20
我按照@Arcesilas (here) 的建议使用了 MySQL 的 date_format
。
我通过合并 start_month
和 start_day
(ex 2017-01-16 = 0116)
[...]
->contain([
'Bookings',
'Amenities',
'Periodicities' => function ($q) use ($check_in, $check_out) {
$start = $q->func()->date_format([
'Periodicities.start' => $check_in->format('Ymd'),
"'%m%d'" => 'literal'
]);
$end = $q->func()->date_format([
'Periodicities.end' => $check_out->format('Ymd'),
"'%m%d'" => 'literal'
]);
return $q
->where(function ($exp) use ($start) {
$exp->between($start, 'Periodicities.start', 'Periodicities.end');
return $exp;
})
->orWhere(function ($exp) use ($end) {
$exp->between($end, 'Periodicities.start', 'Periodicities.end');
return $exp;
});
}
])
[...]
CakephpSQL日志
SELECT
PeriodicitiesRooms.id AS `Periodicities_CJoin__id`,
PeriodicitiesRooms.periodicity_id AS `Periodicities_CJoin__periodicity_id`,
PeriodicitiesRooms.room_id AS `Periodicities_CJoin__room_id`,
PeriodicitiesRooms.price AS `Periodicities_CJoin__price`,
Periodicities.id AS `Periodicities__id`,
Periodicities.name AS `Periodicities__name`,
Periodicities.start AS `Periodicities__start`,
Periodicities.end AS `Periodicities__end`,
Periodicities.price AS `Periodicities__price`,
Periodicities.modified AS `Periodicities__modified`
FROM
periodicities Periodicities
INNER JOIN periodicities_rooms PeriodicitiesRooms ON Periodicities.id = (
PeriodicitiesRooms.periodicity_id
)
WHERE
(
date_format('20170726', '%m%d') BETWEEN 'Periodicities.start'
AND 'Periodicities.end'
OR (
PeriodicitiesRooms.room_id in ('1', '2', '3')
AND date_format('20170720', '%m%d') BETWEEN 'Periodicities.start'
AND 'Periodicities.end'
)
)
这不会再给我任何结果,因为 CakePHP 的 ORM 在 BETWEEN' Periodicities.start 'AND' Periodicities.end'
如果我在我的数据库中粘贴不带撇号 (') 的 CakePHP 查询,它会起作用。您是否知道要对我的查询末尾进行哪些更改,使其看起来像这样:BETWEEN 'Periodicities.start' AND 'Periodicities.end'
到 BETWEEN Periodicities.start AND Periodicities.end
?
'SELECT * FROM periodicities WHERE date_format(' . $check_in->format('Ymd') . ', '%m%d') BETWEEN start AND end'
编辑
从您的评论中我看到您不想存储年份,因为年份不相关。
在这种情况下,您仍然可以将所有日期存储为特定年份,然后将该年份硬编码到查询中。我已将查询修改为使用 2000 年。
原版
我不清楚对话内容,但我会尝试回答您提出的问题。
您似乎想知道如何查找签入时间之间的 Periodicities 或结帐时间之间的 Periodicities。
您似乎还想知道存储日期的最佳方式。
- 只需将日期存储为日期。没必要搞复杂
Between
也太复杂了。
这将完成您需要它做的事情而不会造成混淆。
[...]
->contain([
'Bookings',
'Amenities',
'Periodicities' => function ($q) use ($check_in, $check_out) {
$q->where([
'Periodicities.start >' => $check_in->format('2000-m-d'),
'Periodicities.end <' => $check_in->format('2000-m-d')
]);
$q->orWhere([
'Periodicities.start >' => $check_out->format('2000-m-d'),
'Periodicities.end <' => $check_out->format('2000-m-d')
]);
return $q;
}
])
[...]
我用这个查询解决了我的问题:
->contain([
'Bookings',
'Amenities',
'Periodicities' => function ($q) use ($check_in, $check_out) {
$q->where(function ($exp) use ($check_in, $check_out) {
$exp->gte('Periodicities.start', $check_in->format('md'));
$exp->lte('Periodicities.end', $check_out->format('md'));
});
return $q;
}
])
我一直以 month
和 day
md
格式在数据库中存储日期
例如:0901 < 1030
9 月 1 日 < 10 月 30 日