С Impala в качестве диалекта dbms и SQL вы сможете использовать обычные табличные выражения, но не рекурсию.Кроме того, могут быть проблемы с вставкой параметров.
Ниже приведено непроверенное предложение, которое потребует от вас найти некоторые варианты функций.Сначала он генерирует набор строк с целым числом от 0 до 999 (в примере).При необходимости достаточно легко увеличить количество строк.Из этих строк можно добавить количество дней к литералу отметки времени, используя date_add(timestamp startdate, int days/interval expression)
, а затем с помощью year(timestamp date)
и month(timestamp date)
и day(timestamp date)
см. Функции даты и времени для создания столбцов, необходимых дляв соответствии с вашими данными.
В целом вы сможете построить общее табличное выражение, содержащее столбцы для года, месяца и дня, которые охватывают требуемый диапазон, и которое вы можете внутренне присоединить к исходной таблице и тем самымреализация фильтра диапазона дат.
Приведенный ниже код был создан с использованием T-SQL (SQL Server), и его можно протестировать здесь .
-- produce a set of integers, adjust to suit needed number of these
;WITH
cteDigits AS (
SELECT 0 AS digit UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
, cteTally AS (
SELECT
d1s.digit
+ d10s.digit * 10
+ d100s.digit * 100 /* add more like this as needed */
-- + d1000s.digit * 1000 /* add more like this as needed */
AS num
FROM cteDigits d1s
CROSS JOIN cteDigits d10s
CROSS JOIN cteDigits d100s /* add more like this as needed */
-- CROSS JOIN cteDigits d1000s /* add more like this as needed */
)
, DateRange AS (
select
num
, dateadd(day,num,'20181227') dt
, year(dateadd(day,num,'20181227')) yr
, month(dateadd(day,num,'20181227')) mn
, day(dateadd(day,num,'20181227')) dy
from cteTally
where num < 10
)
select
*
from DateRange
I думаю это эквиваленты Impala для вызовов функций, использованных выше:
, DateRange AS (
select
num
, date_add(to_timestamp('20181227','yyyyMMdd'),num) dt
, year( date_add(to_timestamp('20181227','yyyyMMdd'),num) ) yr
, month( date_add(to_timestamp('20181227','yyyyMMdd'),num) ) mn
, day( date_add(to_timestamp('20181227','yyyyMMdd'),num) ) dy
from cteTally
where num < 10
Надеюсь, вы сможете решить, как их использовать.В конечном итоге цель состоит в том, чтобы использовать сгенерированный диапазон дат следующим образом:
select * from mydb t
inner join DateRange on t.year = DateRange.yr and t.month = DateRange.mn and t.day = DateRange.dy
оригинальное сообщение
Хорошо, если не знать, какую базу данных предложить решениядля, вот предложение с использованием SQL Server:
Это предложение включает в себя рекурсивное общее табличное выражение, которое затем может использоваться как внутреннее соединение с вашими исходными данными, чтобы ограничить результаты диапазоном дат.
--Sql Server 2014 Express Edition
--https://rextester.com/l/sql_server_online_compiler
declare @yr as integer = 2018
declare @mn as integer = 12
declare @dy as integer = 27
declare @du as integer = 10
;with CTE as (
select
datefromparts(@yr, @mn, @dy) as dt
, @yr as yr
, @mn as mn
, @dy as dy
union all
select
dateadd(dd,1,cte.dt)
, datepart(year,dateadd(dd,1,cte.dt))
, datepart(month,dateadd(dd,1,cte.dt))
, datepart(day,dateadd(dd,1,cte.dt))
from cte
where cte.dt < dateadd(dd,@du-1,datefromparts(@yr, @mn, @dy))
)
select
*
from cte
Это приводит к следующему результату:
+----+---------------------+------+----+----+
| | dt | yr | mn | dy |
+----+---------------------+------+----+----+
| 1 | 27.12.2018 00:00:00 | 2018 | 12 | 27 |
| 2 | 28.12.2018 00:00:00 | 2018 | 12 | 28 |
| 3 | 29.12.2018 00:00:00 | 2018 | 12 | 29 |
| 4 | 30.12.2018 00:00:00 | 2018 | 12 | 30 |
| 5 | 31.12.2018 00:00:00 | 2018 | 12 | 31 |
| 6 | 01.01.2019 00:00:00 | 2019 | 1 | 1 |
| 7 | 02.01.2019 00:00:00 | 2019 | 1 | 2 |
| 8 | 03.01.2019 00:00:00 | 2019 | 1 | 3 |
| 9 | 04.01.2019 00:00:00 | 2019 | 1 | 4 |
| 10 | 05.01.2019 00:00:00 | 2019 | 1 | 5 |
+----+---------------------+------+----+----+
и:
select * from mydb t
inner join cte on t.year = cte.yr and t.month = cte.mn and t.day = cte.dy
Вместо рекурсивного выражения общей таблицы вместо него можно использовать таблицу целых чисел (или использоватьнабор объединенных запросов на выборку для генерации набора целых чисел) - часто называемый таблицей подсчета.Выбор одного метода будет зависеть от типа и версии dbms.
Опять же, в зависимости от базы данных, может оказаться более эффективным сохранить результат, представленный выше, как временную таблицу и добавить к ней индекс.