SQL-запрос для определения статуса?

У меня есть таблица в базе данных MSSQL, которая выглядит так:

Timestamp (datetime)
Message (varchar(20))

Раз в день конкретный процесс вставляет текущее время и сообщение «Запущено» при запуске. По завершении вставляет текущее время и сообщение «Готово».

Что такое хороший запрос или набор инструкций, которые, учитывая конкретную дату, возвращают:

  • 0, если процесс никогда не запускался
  • 1, если процесс начался, но не завершился
  • 2, если процесс начался и закончился

В таблице есть и другие сообщения, но «Начато» и «Завершено» уникальны для этого процесса.

Обновлено: для бонусной кармы выдайте ошибку, если данные недействительны, например, есть два сообщения «Начато» или «Завершено» без «Начато».

может ли процесс перенести на следующий день? например Он начинается в 23:59:59 и заканчивается на следующий день.

Matt Rogish 23.09.2008 21:13

Возможно, это будет статус 1 для первого дня и ошибка на следующий день.

Matt Howells 23.09.2008 21:14
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
3
2
1 425
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Select Count(Message) As Status
From   Process_monitor
Where  TimeStamp >= '20080923'
       And TimeStamp < '20080924'
       And (Message = 'Started' or Message = 'Finished')

Вы можете немного изменить это, чтобы обнаруживать недопустимые условия, такие как несколько запусков, завершение, запуск без завершения и т. д.

Select  Case When SumStarted = 0 And SumFinished = 0 Then 'Not Started'
             When SumStarted = 1 And SumFinished = 0 Then 'Started'
             When SumStarted = 1 And SumFinished = 1 Then 'Finished'
             When SumStarted > 1 Then 'Multiple Starts' 
             When SumFinished > 1 Then 'Multiple Finish'
             When SumFinished > 0 And SumStarted = 0 Then 'Finish Without Start'
             End As StatusMessage
From    (
          Select Sum(Case When Message = 'Started' Then 1 Else 0 End) As SumStarted,
                 Sum(Case When Message = 'Finished' Then 1 Else 0 End) As SumFinished
          From   Process_monitor
          Where  TimeStamp >= '20080923'
                 And TimeStamp < '20080924'
                 And (Message = 'Started' or Message = 'Finished')
        ) As AliasName

Опечатка во второй строке кода обнаружения недопустимых условий. Должно быть '... AndSumFinished = 0 Then ...'. Но хороший ответ.

Matt Howells 24.09.2008 17:52

DECLARE @TargetDate datetime
SET @TargetDate = '2008-01-01'

DECLARE @Messages varchar(max)

SET @Messages = ''

SELECT @Messages = @Messages + '|' + Message
FROM process_monitor
WHERE @TargetDate <= Timestamp and Timestamp < DateAdd(dd, 1, @TargetDate)
   and Message in ('Finished', 'Started')
ORDER BY Timestamp desc

SELECT CASE
  WHEN @Messages = '|Finished|Started' THEN 2
  WHEN @Messages = '|Started' THEN 1
  WHEN @Messages = '' THEN 0
  ELSE -1
END

Отредактировано: старый код позволял возвращать случай «Завершено перед запуском» 2.

Amy B 23.09.2008 22:04

Ваш случай обработки ошибок вернет -1, если в таблице есть другие сообщения.

Matt Howells 24.09.2008 12:04

Работает по назначению! (если вы хотите отфильтровать, конструкция для этого - предложение where).

Amy B 24.09.2008 13:57

Да, я просто указываю на то, что в таблице допустимо наличие других сообщений, поэтому возвращать -1, когда они есть, на самом деле неверно.

Matt Howells 24.09.2008 14:19

select count(*) from process_monitor 
where timestamp > yesterday and timestamp < tomorrow.

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

select * from process_monitor where 
timestamp=(select max(timestamp) where timestamp<next_day);

Вам не хватает столбца, который однозначно идентифицирует процесс. Давайте добавим столбец типа int с именем ProcessID. Вам также понадобится другая таблица для идентификации процессов. Если бы вы полагались на свою исходную таблицу, вы бы никогда не узнали о процессах, которые никогда не запускались, потому что для этого процесса не было бы никакой строки.

select
    ProcessID,
    ProcessName,

    CASE
    WHEN 
       (Select 
           COUNT(*) 
        from 
           ProcessActivity 
        where 
           ProcessActivity.processid = Processes.processid 
           and Message = 'STARTED') = 1 

        And
       (Select 
           COUNT(*) 
        from 
           ProcessActivity 
        where 
           ProcessActivity.processid = Processes.processid 
           and Message = 'FINISHED') = 0
     THEN 1

     WHEN
       (Select 
           COUNT(*) 
        from 
           ProcessActivity 
        where 
           ProcessActivity.processid = Processes.processid 
           and Message = 'STARTED') = 1 
       And
       (Select 
           COUNT(*) 
        from 
           ProcessActivity 
        where 
           ProcessActivity.processid = Processes.processid 
           and Message = 'FINISHED') = 1 
THEN 2
     ELSE 0

END as Status

From
    Processes

Строки «Начато» и «Завершено» уникальны для одного процесса. Я упрощал. Если это поможет, подумайте о них как о «Process1Started» и «Process1Finished», где меня интересует только процесс 1.

Matt Howells 23.09.2008 21:01

Другие вопросы по теме