SET time_zone = 'UTC';
SELECT `id`, FROM_UNIXTIME(`time`), FROM_UNIXTIME(7200 * FLOOR(`time` / 7200))
FROM `visitor_stat`
| id | FROM_UNIXTIME(`time`) | interval |
| --- | --------------------- | ------------------- |
| 9 | 2022-09-03 07:00:57 | 2022-09-03 06:00:00 |
| 14 | 2022-09-03 15:17:51 | 2022-09-03 14:00:00 |
| 15 | 2022-09-03 21:47:50 | 2022-09-03 20:00:00 |
| 17 | 2022-09-03 23:16:40 | 2022-09-03 22:00:00 |
Всё красиво, всё совпадает. Теперь поставим другую зону.SET time_zone = 'Europe/Moscow';
SELECT `id`, FROM_UNIXTIME(`time`), FROM_UNIXTIME(7200 * FLOOR(`time` / 7200))
FROM `visitor_stat`
| id | FROM_UNIXTIME(`time`) | interval |
| --- | --------------------- | ------------------- |
| 9 | 2022-09-03 10:00:57 | 2022-09-03 09:00:00 |
| 14 | 2022-09-03 18:17:51 | 2022-09-03 17:00:00 |
| 15 | 2022-09-04 00:47:50 | 2022-09-03 23:00:00 |
| 17 | 2022-09-04 02:16:40 | 2022-09-04 01:00:00 |
Что мы видим? Поскольку зона у нас +03:00, то всё время сдвинулось на нечётное количество часов. Значит работать надо не с математическими операциями, а с функциями времени.SET time_zone = 'Europe/Moscow';
SELECT CAST(CONCAT(`t`.`hour`, ':00') AS TIME) AS `interval`, COUNT(`id`) as `count`
FROM (
SELECT 0 AS `hour`
UNION ALL SELECT 2
UNION ALL SELECT 4
UNION ALL SELECT 6
UNION ALL SELECT 8
UNION ALL SELECT 10
UNION ALL SELECT 12
UNION ALL SELECT 14
UNION ALL SELECT 16
UNION ALL SELECT 18
UNION ALL SELECT 20
UNION ALL SELECT 22
) AS `t`
LEFT JOIN `visitor_stat` AS `v`
ON HOUR(FROM_UNIXTIME(`v`.`time`)) BETWEEN `t`.`hour` AND `t`.`hour` + 1
GROUP BY `t`.`hour`
| interval | count |
| -------- | ----- |
| 00:00:00 | 2 |
| 02:00:00 | 2 |
| 04:00:00 | 0 |
| 06:00:00 | 0 |
| 08:00:00 | 0 |
| 10:00:00 | 5 |
| 12:00:00 | 0 |
| 14:00:00 | 0 |
| 16:00:00 | 0 |
| 18:00:00 | 1 |
| 20:00:00 | 0 |
| 22:00:00 | 0 |
Правда, запрос получится небыстрый, поскольку в условии JOIN'a функция и индекс неприменим, $array = [
2 => [
['product_name' => 'Холодильник 3'],
['product_name' => 'Холодильник 2']
],
1 => [
['product_name' => 'Холодильник'],
]
];
foreach ($array as $shopId => $goods) {
echo $shopId, ' => ', json_encode($goods, JSON_UNESCAPED_UNICODE) . "\n";
}
// 2 => [{"product_name":"Холодильник 3"},{"product_name":"Холодильник 2"}]
// 1 => [{"product_name":"Холодильник"}]
Как видите, к каждому shopId относится только свой набор товаров. SELECT `t`.`from` AS `interval`, COUNT(*) AS `count`
FROM (
SELECT CAST('00:00' AS TIME) AS `from`, CAST('01:00' AS TIME) AS `to`
UNION ALL SELECT CAST('01:00' AS TIME), CAST('02:00' AS TIME)
...
UNION ALL SELECT CAST('23:00' AS TIME), CAST('24:00' AS TIME)
) AS `t`
LEFT JOIN `visitor_stat` AS `v`
ON `v`.`time` >= `t`.`from` AND `v`.`time` < `t`.`to`
WHERE `date` >= :sTime AND `date <= :eTime
GROUP BY `t`.`from`
ORDER BY `t`.`from`
Проверка подписи также осуществляется на сервере. Из header читаются алгоритмы, по ним вычисляется хэш от двух первых частей токена и расшифровывается подпись. Вычисленный хэш должен совпасть с расшифрованным.
Оба ключа, закрытый и открытый хранятся на серверах, закрытый на сервере, выдающем токен, открытый на серверах, проверяющих токен. Естественно, это может быть один и тот же сервер.
https://jwt.io/