Извлечь состояние сигнала в течение указанного периода времени - PullRequest
2 голосов
/ 02 февраля 2012

В базе данных SQL Server 2005 у меня есть таблица с данными, которые регистрируются, когда сигнал включен или отключен. Упрощенно это выглядит так:

Signal  State       Time
------  --------    ----------------
Alarm1  Disabled    2011-11-15 09:00
Alarm1  Enabled     2011-12-20 13:30
Alarm2  Enabled     2011-11-17 15:01
Alarm2  Disabled    2011-12-15 06:57
Alarm3  Disabled    2011-11-10 11:42
Alarm3  Enabled     2011-12-02 13:12
Alarm3  Disabled    2011-12-24 14:41
Alarm4  Enabled     2011-10-09 13:25
Alarm4  Disabled    2012-01-07 08:29
Alarm5  Disabled    2011-11-19 07:12
Alarm5  Enabled     2011-11-28 15:48
Alarm6  Disabled    2011-12-14 17:29
Alarm6  Enabled     2011-12-23 23:46

(Все строки также имеют столбец идентификатора с уникальным идентификатором.)

Используя T-SQL, я хочу извлечь информацию о том, какие аварийные сигналы были отключены в течение определенного периода времени, например, Декабрь 2011 г. Результат должен состоять не только из тех аварийных сигналов, которые были зарегистрированы как отключенные в этом месяце, но также из аварийных сигналов, которые были отключены ранее и не включены в течение данного периода времени.

Учитывая данные выше, я хотел бы извлечь что-то вроде:

Signal  Disabled            Enabled
------  ----------------    -------
Alarm1  -                   2011-12-20 12:30
Alarm2  2011-12-15 06:57    -
Alarm3  -                   2011-12-02 13:12
Alarm3  2011-12-24 14:41    -
Alarm6  2011-12-14 17:29    2011-12-23 23:46

Любая помощь приветствуется!

Ответы [ 2 ]

1 голос
/ 02 февраля 2012

Упрощенные типы.

DECLARE @t TABLE (AlarmId INT NOT NULL, State BIT NOT NULL, TIME SMALLDATETIME NOT NULL)

INSERT @t
VALUES
(1  ,0,'2011-11-15 09:00')
,(1  ,1,'2011-12-20 13:30')
,(2  ,1,'2011-11-17 15:01')
,(2  ,0,'2011-12-15 06:57')
,(3  ,0,'2011-11-10 11:42')
,(3  ,1,'2011-12-02 13:12')
,(3  ,0,'2011-12-24 14:41')
,(4  ,1,'2011-10-09 13:25')
,(4  ,0,'2012-01-07 08:29')
,(5  ,0,'2011-11-19 07:12')
,(5  ,1,'2011-11-28 15:48')
,(6  ,0,'2011-12-14 17:29')
,(6  ,1,'2011-12-23 23:46')


DECLARE @Start DATETIME = '20111201'

--Initial State DISABLED
;WITH Disabled(AlarmId, Time) AS
(
    SELECT 
        AlarmId,
        Time
    FROM
    (
        SELECT 
            ROW_NUMBER() OVER (PARTITION BY AlarmId ORDER BY Time DESC) Ordinal,
            AlarmId,
            Time,
            State
        FROM @t
        WHERE 
            Time < @Start
    ) t
    WHERE 
        t.Ordinal = 1
    AND t.STate = 0
    UNION
    SELECT
        AlarmId,
        TIME
    FROM @t
    WHERE 
        Time >= @start AND Time < DATEADD(m,1,@STart)
    AND STate = 0

),
Enabled(AlarmId, Time) AS
(
    SELECT 
        AlarmId,
        TIME
    FROM @t
    WHERE 
        Time >= @start AND Time < DATEADD(m,1,@STart)
    AND STate = 1
),
Alarms(AlarmId) AS
(
    SELECT DISTINCT AlarmId FROM @t
)

SELECT 
    Alarms.AlarmId,
    CASE WHEN Disabled.Time >= @start AND Disabled.Time < DATEADD(m,1,@STart) THEN Disabled.Time ELSE NULL END Disabled,
    CASE WHEN Enabled.Time < Disabled.Time THEN NULL ELSE Enabled.Time END Enabled
FROM Alarms 
LEFT JOIN Enabled
    ON Alarms.AlarmId = Enabled.AlarmId
LEFT JOIN Disabled
    ON Alarms.AlarmId = Disabled.AlarmId
WHERE COALESCE(Enabled.Time, Disabled.Time) IS NOT NULL
0 голосов
/ 02 февраля 2012

У меня есть два предложения (в зависимости от того, какие данные вы хотите)

Первые тестовые данные:

DECLARE @tbl TABLE(Signal VARCHAR(100),State  VARCHAR(100),Time DATETIME)
INSERT INTO @tbl
SELECT 'Alarm1','Disabled','2011-11-15 09:00'
UNION ALL
SELECT 'Alarm1','Enabled','2011-12-20 13:30'
UNION ALL
SELECT 'Alarm2','Enabled','2011-11-17 15:01'
UNION ALL
SELECT 'Alarm2','Disabled','2011-12-15 06:57'
UNION ALL
SELECT 'Alarm3','Disabled','2011-11-10 11:42'
UNION ALL
SELECT 'Alarm3','Enabled','2011-12-02 13:12'
UNION ALL
SELECT 'Alarm3','Disabled','2011-12-24 14:41'
UNION ALL
SELECT 'Alarm4','Enabled','2011-10-09 13:25'
UNION ALL
SELECT 'Alarm4','Disabled','2012-01-07 08:29'
UNION ALL
SELECT 'Alarm5','Disabled','2011-11-19 07:12'
UNION ALL
SELECT 'Alarm5','Enabled','2011-11-28 15:48'
UNION ALL
SELECT 'Alarm6','Disabled','2011-12-14 17:29'
UNION ALL
SELECT 'Alarm6','Enabled','2011-12-23 23:46'

DECLARE @startDate DATETIME='2011-12-01'

Тогда, если вы, что тревога не уникальная. Я бы сделал что-то вроде этого:

SELECT
    tbl.Signal,
    CASE 
        WHEN tbl.State='Disabled'
        THEN convert(varchar, tbl.Time, 120)
        ELSE '-'
    END AS DisabledTime,
    CASE 
        WHEN tbl.State='Enabled'
        THEN convert(varchar, tbl.Time, 120)
        ELSE '-'
    END AS EnabledTime
FROM
    @tbl AS tbl
WHERE 
    tbl.Time BETWEEN @startDate AND (DATEADD(MM,1,@startDate)-1)

Если вы знаете, какие тревоги уникальны, я бы сделал что-то вроде этого:

SELECT
    pvt.Signal,
    ISNULL(pvt.Disabled,'-') AS Disabled,
    ISNULL(pvt.Enabled,'-') AS Enabled
FROM
(
    SELECT
        tbl.Signal,
        convert(varchar, tbl.Time, 120) AS Time,
        tbl.State
    FROM
        @tbl AS tbl
    WHERE 
        tbl.Time BETWEEN @startDate AND (DATEADD(MM,1,@startDate)-1)
) AS p
PIVOT
(
    MAX(p.Time)
    FOR p.State IN([Disabled],[Enabled])
) AS pvt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...