#cassandra
Вопрос:
из таблицы Cassandra, как получить записи на основе даты из столбца метки времени.Подробности в таблице
CREATE TABLE hlragent_logs.hlragent_logs_2021 (
msisdn text,
date_time timestamp,
cmd_no text,
agent_id text,
cmd_executed text,
dummy text,
id bigint,
imsi text,
mml_cmd text,
module text,
node text,
node_id text,
node_ip text,
p text,
pno text,
serial text,
vhlr_name text,
PRIMARY KEY (msisdn, date_time, cmd_no)
) WITH CLUSTERING ORDER BY (date_time ASC, cmd_no ASC)
AND bloom_filter_fp_chance = 0.01
AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
AND comment = ''
AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
AND crc_check_chance = 1.0
AND dclocal_read_repair_chance = 0.1
AND default_time_to_live = 0
AND gc_grace_seconds = 864000
AND max_index_interval = 2048
AND memtable_flush_period_in_ms = 0
AND min_index_interval = 128
AND read_repair_chance = 0.0
AND speculative_retry = '99PERCENTILE';
CREATE INDEX indx_agentlogs_2021 ON hlragent_logs.hlragent_logs_2021 (imsi)
выберите * из hlragent_logs_2021, где todate(дата и время)=»2021-08-10″ разрешить фильтрацию;
Исключение синтаксиса: строка 1:45 нет жизнеспособной альтернативы на входе ‘(‘ (выберите * из hlragent_logs_2021, где указать
Ответ №1:
Вы не можете использовать пользовательские функции в WHERE
предложении (для этого есть билет Jira, но я не помню, чтобы кто-то работал над ним).
Комментарии:
1. todate-это функция отметки времени для управления датами, используемыми в операторах INSERT, UPDATE и SELECT. выберите * из hlragent_logs_2021, где date_time>=’2021-08-10′ и mml_cmd=’УДАЛИТЬ ПОЛЬЗОВАТЕЛЯ» разрешить фильтрацию это уокинг
2. Я знаю, что
todate
это такое — вы просто не можете использовать его в состоянии «где». Вы можете изучить грамматику CQL, чтобы убедиться, что функции не поддерживаются: github.com/apache/cassandra/blob/trunk/src/antlr/Parser.g#L1672
Ответ №2:
Нет необходимости использовать собственную TODATE()
функцию CQL для работы со столбцами временных меток. Можно напрямую работать с колонкой с помощью:
SELECT * FROM ... WHERE ... AND date_time < "2021-08-10";
Но вы не можете использовать оператор равенства ( =
), потому что тип данных метки времени CQL кодируется как количество миллисекунд с эпохи Unix (1 января 1970 года 00:00 по Гринвичу), поэтому вам нужно быть точным при работе с метками времени.
В зависимости от того, где вы выполняете запрос, фильтр может быть переведен в местный часовой пояс. Позвольте мне проиллюстрировать это примером таблицы:
CREATE TABLE community.tstamptbl (
id int,
tstamp timestamp,
PRIMARY KEY (id, tstamp)
)
Эти 2 утверждения могут показаться похожими, но переводятся в 2 разные записи:
INSERT INTO tstamptbl (id, tstamp) VALUES (5, '2021-08-09');
INSERT INTO tstamptbl (id, tstamp) VALUES (5, '2021-08-09 0000');
Первая инструкция создает запись с меткой времени в моем локальном часовом поясе (Мельбурн, Австралия), в то время как вторая инструкция создает запись с меткой времени в формате UTC ( 0000
):
cqlsh:community> SELECT * FROM tstamptbl WHERE id = 5;
id | tstamp
---- ---------------------------------
5 | 2021-08-08 14:00:00.000000 0000
5 | 2021-08-09 00:00:00.000000 0000
Точно так же вам нужно быть точным при считывании данных. Вам нужно указать часовой пояс, чтобы устранить двусмысленность. Вот несколько примеров:
SELECT * FROM tstamptbl WHERE id = 5 AND tstamp < '2021-08-09 0000';
SELECT * FROM tstamptbl WHERE id = 5 AND tstamp < '2021-08-10 12:00 0000';
SELECT * FROM tstamptbl WHERE id = 5 AND tstamp < '2021-08-08 12:34:56 0000';
Опять же, поскольку временные метки кодируются в миллисекундах (вместо дней), существует целый диапазон возможных значений для данной даты. Если я хотел получить все строки для даты 2021-08-09
, мне нужно отфильтровать их на основе диапазона, как в этом примере:
SELECT * FROM tstamptbl
WHERE id = 5
AND tstamp >= '2021-08-09 0000'
AND tstamp < '2021-08-10 0000';
Ваше здоровье!