Я пытаюсь обработать данные, хранящиеся на сервере KDB+, с помощью блокнота Jupyter. Вот как я подключился к серверу:
connection = kx.QConnection(host='localhost', port=5000)
Затем O прочитайте файл csv, используя:
table1 = connection.read.csv("path/to/file", schema)
После этого я записал таблицу table1 в базу данных:
connection('insert', 'table1', conn_table1)
Мне нужно реализовать следующее, что не работает:
start_date = "3/6/2015 12:44:31"
end_date = "3/6/2020 12:44:31"
connection(f'select col1 datetimecol2 by col1 from table1 where col3<`2 & datetimecol2 within (`${start_date};`${end_date})')
Как я могу это сделать с помощью KDB+? И где я могу найти хороший ресурс для изучения KDB+?
Спасибо!
Я ожидал получить какие-то результаты, но вместо этого получил ошибку: QError: /
В запросе, который вы пытаетесь выполнить, есть несколько изменений, которые должны конкретно разблокировать этот запрос.
Ошибка, которую вызывает q в этом случае, конкретно связана с /
в ваших объектах datetime, чтобы решить эту проблему, вы можете передать их как строки в формате q или, возможно, более полезно передать дату и время напрямую. PyKX преобразует их из представления даты и времени в эквивалент PyKX.
from datetime import datetime
start_date=datetime.strptime("03/6/2015 12:44:31", '%m/%d/%Y %H:%M:%S')
end_date=datetime.strptime("03/6/2020 12:44:31", '%m/%d/%Y %H:%M:%S')
connection('{select datetimecol2 by col1 from table1 where col3<2, datetimecol2 within (x;y)}', start_date, end_date)
Что касается ресурсов по стороне q, книга q-for-mortals доступна по адресу https://code.kx.com/q4m3/ — отличный ресурс для начала работы со всеми элементами q, в вашем случае для в этом примере раздел q-sql здесь может представлять интерес
Ваш запрос строится на:
select col1 datetimecol2 by col1 from table1
where col3<`2 & datetimecol2 within (`$3/6/2015 12:44:31;`$3/6/2020 12:44:31)
Проблемы:
,
между именами столбцов col1 datetimecol2
, это может привести к попытке использования datetimecol2
для индексации в col1
, а я предполагаю, что это не то, что вы намеревались сделать. Если datetimecol2
является типом символа, эта операция завершится неудачей с type
.col1
слева и справа от by
, это запрещено и приведет к ошибке 'dup names for cols/groups col1
и /
). Их необходимо завернуть в ""
col3<`2
, выполняя операцию «меньше» над типом данных символа. Хотя технически это может работать, скорее всего, вам нужен числовой столбец и сравнение.&
по умолчанию. ,
разделяет предложенияwhereРеализация исправлений 1–5 дает работоспособный запрос:
select datetimecol2 by col1 from table1
where col3<2, datetimecol2 within (`$"3/6/2015 12:44:31";`$"3/6/2020 12:44:31")
Ваш формат временной метки можно проанализировать с помощью q:
q)"P"$"3/6/2015 12:44:31"
2015.03.06D12:44:31.000000000
Итак, в вашей схеме вы должны использовать больше похожего на:
schema = {'col3':kx.LongAtom,
'datetimecol2':kx.TimestampAtom,
}
Тогда ваш запрос должен передавать параметры, а не создавать сложные строки:
from datetime import datetime
start_date = datetime.strptime("3/6/2015 12:44:31",'%m/%d/%Y %H:%M:%S')
end_date=datetime.strptime("3/6/2020 12:44:31",'%m/%d/%Y %H:%M:%S')
connection('{select datetimecol2 by col1 from table1 where
col3<2, datetimecol2 within (x;y)}',
start_date, end_date)
Видеть:
В Академии KX есть курсы, по которым вы можете изучить q/kdb+ и PyKX. https://learninghub.kx.com/academy/
Это сработало, спасибо! Я заметил, что `timesstamp$datatime1 выполняется быстрее, чем "P"$"datetime1". Это правильно?
Нет, это cast , вам нужно tok для анализа строки.
Извините, я проверил каст и ток, но не заметил разницы. Не могли бы вы объяснить мне их подробнее, пожалуйста?
"I"$"10"
— это tok
и будет анализировать строку. Выход 10i
. `int$"10"
есть cast
и приводит данные. Выведите 49 48i
, потому что каждый символ преобразуется индивидуально. Числа 49
и 48
и базовые значения ASCII для "1"
и "0"
asciitable.comПротестировав q)`timestamp$"3/6/2015 12:44:31"
, вы увидите выходные данные 2000.01.01D00:00:00.000000051 2000.01.01D00:00:00.000000047 2000.01.01D00:00:00.000000054 2000.01.01D00:00:00.000000047 2000.01.01D00:00:00.000000050 2000.01.01D00:0..
, поскольку он пытается индивидуально привести каждый символ к временной метке. Это не то, чего вы хотите. "P"$"3/6/2015 12:44:31"
анализирует его до правильной временной метки 2015.03.06D12:44:31.000000000
Понятно! Спасибо, вы цените это!
Спасибо! Судя по всему, KDB+ принимает даты, разделенные точкой, а не косой чертой, поэтому мне пришлось провести некоторую реструктуризацию кода, но в конечном итоге это сработало, спасибо!