Как повторить значения в таблице в SQL Server? - PullRequest
0 голосов
/ 28 октября 2019

У меня есть таблица в Microsoft SQL Server, в которой записаны некоторые значения триггеров изменения данных. Теперь, чтобы отобразить некоторые графики, я хотел бы получить (или повторить) значение за 10 минут из каждого столбца (например).

Я бы попытался, если возможно, избежать изменения команды INSERTсама таблица.

Исходная таблица:

Time Stamp---- | A | B | C |
---------------+---+---+---+
01-01-19 10:20 | 1 | 0 | 0 |
01-01-19 15:30 | 0 | 0 | 1 |
01-01-19 22:50 | 0 | 1 | 0 |
02-01-19 01:40 | 1 | 0 | 0 |
...

Результат, которого я хотел бы достичь:

Time Stamp---- | A | B | C |
---------------+---+---+---+
01-01-19 10:20 | 1 | 0 | 0 |
01-01-19 10:30 | 1 | 0 | 0 |
01-01-19 10:40 | 1 | 0 | 0 |
01-01-19 10:50 | 1 | 0 | 0 |
... 
01-01-19 15:30 | 0 | 0 | 1 |
01-01-19 15:40 | 0 | 0 | 1 |
01-01-19 15:50 | 0 | 0 | 1 |
01-01-19 16:00 | 0 | 0 | 1 |
...

Ответы [ 4 ]

0 голосов
/ 28 октября 2019

Можно использовать SQL RECURSION и CROSS JOIN

SQL FIDDLE

Демо

declare @mytable as table(timestamp datetime,A int,B int,C int)

insert into @mytable values
('01-01-19 10:20',1,0,0),('01-01-19 15:30',0,0,1),
('01-01-19 22:50',0,1,0),('01-01-19 01:40',1,0,0)

;with cte as(
select 0 n 
union all
select n+10 from cte where n+10 <40)
select dateadd(mi,n,timestamp)[TIMESTAMP],t1.A,t1.B,T1.C 
from @mytable t1 cross join cte 
order by timestamp
0 голосов
/ 28 октября 2019

Лично я рекомендую создать «Расписание», но я делаю это на лету, используя Tally. Во всяком случае, я думаю это то, что вы ищете?

USE Sandbox;
GO

CREATE TABLE dbo.YourTable ([timestamp] datetime2(0), --This is a bad name for a column, as timestamp means soemthing else in SQL Server
                            A bit,
                            B bit,
                            C bit);
INSERT INTO dbo.YourTable ([timestamp],
                           A,
                           B,
                           C)
VALUES ('2019-01-01T10:20:00',1,0,0),
       ('2019-01-01T15:30:00',0,0,1),
       ('2019-01-01T22:50:00',0,1,0),
       ('2019-01-02T01:40:00',1,0,0);

GO

WITH N AS
    (SELECT N
     FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT TOP(144) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
    FROM N N1, N N2, N N3),
Times AS(
    SELECT DATEADD(MINUTE,T.I * 10,CONVERT(time(0),'00:00:00')) AS TimeSlot
    FROM Tally T),
DateTimes AS(
    SELECT DISTINCT
           CONVERT(datetime,CONVERT(date,YT.[timestamp])) + CONVERT(datetime,T.TimeSlot) AS DateTimeSlot
    FROM dbo.YourTable YT
         CROSS JOIN Times T),
Groups AS(
    SELECT DT.DateTimeSlot,
           CONVERT(tinyint,YT.A) AS A, --Can't aggregate Bits
           CONVERT(tinyint,YT.B) AS B,
           CONVERT(tinyint,YT.C) AS C,
           COUNT(YT.A) OVER (ORDER BY DT.DateTimeSlot ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
    FROM DateTimes DT
         LEFT JOIN dbo.YourTable YT ON DT.DateTimeSlot = YT.[timestamp])
SELECT G.DateTimeSlot,
       MAX(G.A) OVER (PARTITION BY G.Grp) AS A,
       MAX(G.B) OVER (PARTITION BY G.Grp) AS B,
       MAX(G.C) OVER (PARTITION BY G.Grp) AS C
FROM Groups G
ORDER BY G.DateTimeSlot;

GO

DROP TABLE dbo.YourTable;
0 голосов
/ 28 октября 2019

Предполагая, что ваши даты - мм-дд-гг, а время - чч: мм ...

create table #Original (
    [Time Stamp----] datetime2,
    A int,
    B int,
    C int
)

insert #Original
values ({ts '2019-01-01 10:20:00.000'}, 1, 0, 0)
     , ({ts '2019-01-01 15:30:00.000'}, 0, 0, 1)
     , ({ts '2019-01-01 22:50:00.000'}, 0, 1, 0)
     , ({ts '2019-01-02 01:40:00.000'}, 1, 0, 0)

;
with 
boundaries as (
    select min(o.[Time Stamp----]) as s
    , dateadd(minute, 10, max(o.[Time Stamp----])) as e
    from #Original o
),
timeslist as (
    select 1 as i
    , (select s from boundaries) as s
    , (select s from boundaries) as d

    union all
    select t.i + 1
    , t.s
    , dateadd(minute, 10, d)
    from timeslist t
    where d < (select e from boundaries)
),
result as (
    select 
      right('0' + cast(MONTH(t.d) as varchar(2)), 2) + '-' + 
      right('0' + cast(DAY(t.d) as varchar(2)), 2) + '-' + 
      right('0' + cast(year(t.d) % 100 as varchar(2)), 2) + ' ' + 
      right('0' + cast(datepart(hour, t.d) as varchar(2)), 2) + ':' + 
      right('0' + cast(datepart(minute, t.d) as varchar(2)), 2) as 'Time Stamp----'
    , o2.A
    , o2.B
    , o2.C

    from timeslist t
      inner join (
        select o.[Time Stamp----]
        , o.A
        , o.B
        , o.C
        , lead (o.[Time Stamp----], 1, dateadd(minute, 10, o.[Time Stamp----])) over (order by o.[Time Stamp----]) as OldTs
        from #Original o
      ) o2 on o2.[Time Stamp----] <= t.d and o2.OldTs > t.d
)

select *
from result
order by [Time Stamp----]


drop table #Original
0 голосов
/ 28 октября 2019
To select records with manufactured duplicates, try

    SELECT Dateadd(mi, DQ.T,TimeStamp) as 'TimeStamp', A, B, C From YourTable 
        CROSS JOIN (Select 0 T UNION ALL 
                    Select 10 T UNION ALL 
                    Select 20 T UNION ALL 
                    Select 30 T) DQ

или для вставки дубликатов, попробуйте

INSERT YourTable 
    SELECT Dateadd(mi, DQ.T,TimeStamp) as 'TimeStamp', A, B, C From YourTable 
        CROSS JOIN (
                    Select 10 T UNION ALL 
                    Select 20 T UNION ALL 
                    Select 30 T) DQ
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...