Как я могу правильно настроить запрос, чтобы получить конкретный c результат SQL - PullRequest
0 голосов
/ 06 августа 2020

Мне нужно сделать 2 отчета из таблицы, которую я показываю ниже.

  1. Мне нужен один отчет, чтобы увидеть всех детей, которые еще учатся в школе на момент выполнения отчета

  2. Мне нужен один отчет, чтобы указать количество часов, проведенных каждым ребенком в школе. Для детей, которые еще учатся в школе, количество часов на момент поступления в школу и текущее время.

Можете ли вы помочь мне правильно установить logi c для этих двух случаев?

Подробное объяснение:

  • Например, Джон в какой-то момент выехал из дома и go в школу, затем через несколько минут он направился в библиотеку (Школа -> Библиотека). Через некоторое время он снова выходит из (Библиотека -> Школа), а в конце - из (Школа -> Дом). С другими ребятами такая же история.

  • Теперь у меня проблемы с установкой logi c, чтобы получить эти 2 случая и правильно настроить запросы.

Заранее спасибо :)

IF OBJECT_ID('tempdb..#temp') IS NOT NULL 
    DROP TABLE #temp
GO

CREATE TABLE #temp 
(
    Person nvarchar(max), 
    src_location nvarchar(max),  
    dst_location nvarchar(max), 
    [time] datetime 
)
GO

INSERT INTO #temp (person, src_location, dst_location, time) 
VALUES ('John', 'House', 'School', '2018-08-31 08:53:55'),
       ('Peter', 'House', 'School', '2018-08-31 09:01:55'),
       ('John', 'School', 'Library', '2018-08-31 09:03:14'),
       ('Tina', 'Park', 'School', '2018-08-31 09:10:22'),
       ('John', 'Library', 'School', '2018-08-31 09:50:14'),
       ('John', 'School', 'House', '2018-08-31 00:48:14'),
       ('Tina', 'School', 'House', '2018-08-31 00:15:22'),
       ('John', 'House', 'School', '2018-10-16 08:22:32')

SELECT * FROM #temp

Ответы [ 3 ]

1 голос
/ 06 августа 2020

Я не настолько разбираюсь в MS SQL. Общий способ ответить на ваш первый вопрос - запросить последнюю запись для каждого пользователя (GROUP BY [person]), а затем отфильтровать их для людей, у которых dst_location равно School ([dst_location] = 'School')

Я вижу, что это не работает полностью, так как он все равно возвращает Тину, хотя она уже бросила школу, см. http://sqlfiddle.com/#! 18 / 0b1c8 / 24

0 голосов
/ 10 августа 2020

Тогда вы можете попробовать:

DECLARE @person nvarchar(50), @location nvarchar(50),  
@time datetime, @permanence int, @enters datetime, @exits datetime,
@inside int, @person_sv nvarchar(50);  

SET @inside = 0
DECLARE school CURSOR FOR   
SELECT person, dst_location, time  
FROM #temp  
ORDER BY person, time DESC;  

OPEN school  

SET @person_sv = ''

FETCH NEXT FROM school   
INTO @person, @location, @time  

WHILE @@FETCH_STATUS = 0  
BEGIN  
     IF @person <> @person_sv -- person changed, we had the time!
     BEGIN
         IF @permanence <> 0 -- only person who had been at school
         BEGIN
             IF @location = 'School' -- last location for person, he/she is still in
             BEGIN
                 @permanence += DATEDIFF(h, @enters, GETDATE()
             END
             INSERT INTO #temp2 VALUES (@person_sv, @permanence)
         END 
         SET @person_sv = @person
         SET @permanence = 0
     END
     IF @location = 'School' -- person enters
     BEGIN
         IF @inside = 0 -- person is not in school
         BEGIN
             set @enters = @time
             set @inside = 1 -- now person is in
         END
     END 
     IF @location <> 'School'
     BEGIN
         IF @inside = 1 -- person is in school
         BEGIN
             set @exits = @time
             set @permanence += DATEDIFF(day, @enters, @exits)
             set @inside = 0 -- person had exited
         END
     END 

FETCH NEXT FROM school   
INTO @person, @location, @time  
END   
CLOSE school;  
DEALLOCATE school;  

Не пробовал, извините, но у меня нет работы :)

0 голосов
/ 07 августа 2020

Я нашел хорошее решение для первого случая:

Таблица со всей приведенной ниже информацией:

Person      src_location         dst_location              time                   
----------- -------------------- ------------------------- -----------------------
John        House                School                    2018-08-31 08:53:55.000
Peter       House                School                    2018-08-31 09:01:55.000
John        School               Library                   2018-08-31 09:03:14.000
Tina        Park                 School                    2018-08-31 09:10:22.000
John        Library              School                    2018-08-31 09:50:14.000
John        School               House                     2018-08-31 00:48:14.000
Tina        School               House                     2018-08-31 11:15:22.000
John        House                School                    2018-10-16 08:22:32.000

Разделы по 'person' и упорядочены по 'time' des c и получаем первый результат (из-за порядка по времени ds c в нашем случае это последние результаты для каждого человека).

  WITH KidsAtSchool AS (
SELECT m.person, 
       m.src_location,
       m.dst_location,
       m.time,
       DATEDIFF(day, [time], GETDATE()) AS HoursAtSchool,
       ROW_NUMBER() OVER (PARTITION BY person ORDER BY time DESC) AS rn
  FROM #temp AS m
)

SELECT *
  FROM KidsAtSchool
 WHERE rn = 1 
   AND dst_location = 'School'

Полученные мной результаты верны:)

Person      src_location         dst_location              time                    HoursAtSchool  
----------- -------------------- ------------------------- ----------------------- --------------
John        House                School                    2018-10-16 08:22:32.000   661
Peter       House                School                    2018-08-31 09:01:55.000   707

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

Кроме того, второй случай для меня все еще сложен.

...