Невозможно увеличить значения в CTE T-SQL - PullRequest
0 голосов
/ 29 апреля 2019

У меня есть случай, когда мне нужно написать CTE (по крайней мере, это кажется лучшим подходом).У меня есть почти все, что мне нужно, кроме одного последнего вопроса.Я использую CTE для генерации многих миллионов записей, а затем вставляю их в таблицу.Сами данные практически не имеют значения, за исключением трех столбцов.2 столбца даты и времени и один символьный столбец.

Идея CTE заключается в следующем.Мне нужно одно поле даты и времени с именем Start и одно поле int с именем DataValue.У меня будет переменная, представляющая собой количество записей, к которым я хочу стремиться, а затем еще одна переменная, представляющая собой число повторений значения datetime.Я не думаю, что мне нужно объяснять программное обеспечение, которое представляют эти данные, но в основном мне нужно иметь 16 строк, в которых значение Start одинаково, а затем после 16-го запуска я хочу добавить 15 минут и затем повторить.Фактически, события будут происходить с 15-минутными интервалами, и мне потребуется X рядов на 15-минутный интервал для представления этих событий.

Это мой код

Declare @tot as int;
Declare @inter as int;
Set @tot = 26
Set @inter = 3;

WITH mycte(DataValue,start) AS 
(
SELECT 1 DataValue, cast('01/01/2011 00:00:00' as datetime) as start
UNION all
if DataValue % @inter = 0 
    SELECT 
        DataValue + 1, 
        cast(DateAdd(minute,15,start) as datetime)
else
    select 
        DataValue + ,
        start

FROM    mycte   
WHERE   DataValue + 1 <= @tot)


select  
    m.start,
    m.start,
    m.Datavalue%@inter
from mycte as m
option (maxrecursion 0);

Я заменю оператор выбора на оператор вставки, как только я его заработаю, но m.DataValue%@inter заставит его повторять целое число при вставке, поэтому единственныймне нужно выяснить, как сделать так, чтобы начало было одинаковым 16 раз подряд, а затем увеличить

Кажется, я не могу иметь оператор IF в CTE, но я не уверен, как этого добитьсяно то, что я собирался сделать, это в основном сказать, что если DataValue%16 было 0, то увеличьте значение start.

В конце я надеюсь, что получится что-то подобное, где в этом случае я повторяю это только 4 раза

+-----------+-------------------+
| DateValue |       start       |
+-----------+-------------------+
|         1 | 01/01/01 00:00:00 |
|         2 | 01/01/01 00:00:00 |
|         3 | 01/01/01 00:00:00 |
|         4 | 01/01/01 00:00:00 |
|         5 | 01/01/01 00:15:00 |
|         6 | 01/01/01 00:15:00 |
|         7 | 01/01/01 00:15:00 |
|         8 | 01/01/01 00:15:00 |

Есть ли другой способ сделать это без условных выражений?

Ответы [ 2 ]

1 голос
/ 29 апреля 2019

Вы можете использовать случай, как показано ниже:

Declare @tot as int;
Declare @inter as int;
Set @tot = 26
Set @inter = 3;

WITH mycte(DataValue,start) AS 
(
SELECT 1 DataValue, cast('01/01/2011 00:00:00' as datetime) as start
UNION all

    SELECT DataValue+1 [Datavalue],
        case when (DataValue % @inter) = 0  then cast(DateAdd(minute,15,start) as datetime) else  [start] end [start] 
FROM    mycte   
WHERE   (DataValue + 1) <= @tot)

select  
    m.DataValue,
    m.[start]
from mycte as m
option (maxrecursion 0);

Это даст следующий результат

DataValue    Start
=========    =============
1   2011-01-01 00:00:00.000
2   2011-01-01 00:00:00.000
3   2011-01-01 00:00:00.000
4   2011-01-01 00:15:00.000
5   2011-01-01 00:15:00.000
6   2011-01-01 00:15:00.000
7   2011-01-01 00:30:00.000
8   2011-01-01 00:30:00.000
9   2011-01-01 00:30:00.000
10  2011-01-01 00:45:00.000
11  2011-01-01 00:45:00.000
12  2011-01-01 00:45:00.000
....
26  2011-01-01 02:00:00.000

И если вы не хотите использовать случай, когда вы можете использовать двойной рекурсивный cte, как показано ниже: -

WITH mycte(DataValue,start) AS 
(   --this recursive cte will generate the same record the number of @inter
    SELECT 1 DataValue, cast('01/01/2011 00:00:00' as datetime) as start
    UNION all
    SELECT DataValue+1 [DataValue],[start] 
    FROM    mycte   
    WHERE   (DataValue + 1) <= @inter)
,Increments as (
    -- this recursive cte will do the 15 additions
    select * from mycte
    union all
    select DataValue+@inter [DataValue]
    ,DateAdd(minute,15,[start])  [start]  
    from Increments
    WHERE   (DataValue + 1) <= @tot
)
select  
    m.DataValue,
    m.[start]
from Increments as m
order by DataValue
option (maxrecursion 0);

это даст те же результаты.

0 голосов
/ 29 апреля 2019

Вы можете сделать это с помощью таблицы подсчета и некоторой базовой математики.Я не уверен, что ваши общие строки равны @tot или они должны быть @tot * @inter.Если это так, вам просто нужно изменить предложение TOP.Если вам нужно больше строк, вам просто нужно изменить генерацию таблицы подсчета.

Declare @tot as int;
Declare @inter as int;
Set @tot = 26
Set @inter = 3;

WITH 
E(n) AS(
    SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)
),
E2(n) AS(
    SELECT a.n FROM E a, E b
),
E4(n) AS(
    SELECT a.n FROM E2 a, E2 b
),
cteTally(n) AS(
    SELECT TOP( @tot) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) n
    FROM E4
)
SELECT n, DATEADD( MI, 15* ((n-1)/@inter), '20110101')
FROM cteTally;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...