Я запрашиваю количество входов для каждой двери в день.

Для начала я запрашиваю количество людей, которые входят в соответствующую дверь, которая определяется столбцом door_code, а идентификатор ключа доступа определяется столбцом pass_id. Поэтому я сгруппировал столбец «pass_id», чтобы удалить повторяющихся людей у входа.

SELECT 
    t1.[entrance_date],
    [door_code],
    COUNT([pass_id]) AS [entrance_count]
FROM
    (SELECT
         CONVERT(date, substring(entrance_date, 0, 9)) as [entrance_date],   
         [pass_id], [door_code]
     FROM
         dbo.entrance_history
     WHERE
         door_code IN ('000A', '000B', '000C'....continued)
     GROUP BY
         CONVERT(date, substring(entrance_date, 0, 9)), [pass_id], [door_code]) t1
WHERE
    t1.entrance_date BETWEEN '2018-03-10' AND '2018-03-13' 
GROUP BY 
    [door_code], [entrance_date]
ORDER BY 
    [door_code] DESC, [entrance_date] DESC

Этот запрос возвращает следующий набор результатов:

entrance_date|door_code|entrance_count
2018-03-13   |000C     |9
2018-03-12   |000C     |23
2018-03-11   |000C     |18
2018-03-10   |000C     |19
2018-03-13   |000B     |1
2018-03-12   |000B     |1
2018-03-11   |000B     |1
2018-03-10   |000B     |1
2018-03-12   |000A     |1
.....continued

И я хочу преобразовать это как

entrance_date|000C|000B|000A
2018-03-13   |9   |1   |0
2018-03-12   |23  |1   |1
2018-03-11   |18  |1   |1
2018-03-10   |19  |1   |1

Я попробовал повернуть, как показано ниже, но это не сработало. Я использую SQL Server 2012.

declare @doorCode nvarchar(Max) = '''000A'',''000B'',''000C'''
declare @sql nvarchar(Max);

set @sql = 'select base_table.[enterance_date], '
+ @doorCode +
' from
(SELECT t1.[entrance_date],
[door_code],
count([pass_id]) as [entrance_count]
FROM
(
    select CONVERT(date,substring(entrance_date,0,9)) as [entrance_date], [pass_id], [door_code]
    from dbo.entrance_history
    where door_code in ('+@doorCode+')
    group by CONVERT(date,substring(entrance_date,0,9)),[pass_id], [door_code]
) t1
group by [door_code], [entrance_date]
) as [base_table]
    pivot 
    (
      base_table.enterance_count 
      for base_table.[door_code] in ('+@doorCode+')
    ) as pivottable'

exec sp_executesql @sql
0
ringord 13 Мар 2018 в 08:42

2 ответа

Лучший ответ

Ответ узи частично правильный. Хотя достаточно использовать одну группировку, идентификатор прохода должен быть включен в предложение группировки, чтобы мы могли удалить повторяющуюся входную запись людей. Я пытался узнать количество людей , вошедших в дверь, а не количество подъездов.

Для этого я сначала запрашиваю количество входов для каждого pass_id , как показано ниже.

entrance_date|door_code|entrance_count|pass_id
2018-03-13   |000C     |4             |P0001
2018-03-13   |000C     |2             |P0002
2018-03-13   |000C     |1             |P0003
2018-03-13   |000C     |1             |P0004
2018-03-13   |000B     |1             |P0001
2018-03-13   |000B     |1             |P0002
2018-03-13   |000B     |1             |P0003
2018-03-13   |000B     |1             |P0004
2018-03-13   |000A     |1             |P0001
.... continued

Результат выше возвращается запросом ниже.

select 
  CONVERT(date,substring(entrance_date,0,9)) as [entrance_date],  [door_code], count([pass_id]) as [entrance_count], [pass_id]
  from dbo.entrance_history
  where door_code in ('000A', '000B', '000C'....continued)
  group by CONVERT(date,substring(entrance_date,0,9)), [door_code], [pass_id]

Теперь мне нужно повернуть приведенную выше таблицу, чтобы получить нужный набор данных. Чтобы получить количество людей (которое определяется столбцом «pass_id», согласно правилу 1 проход на 1 человека), мне нужно подсчитать pass_id. Тогда я получаю этот запрос.

declare @doorCode nvarchar(Max) = '''000A'',''000B'',''000C'''
declare @doorCode2 nvarchar(Max) = '[000A],[000B],[000C]'
declare @sql nvarchar(Max);

set @sql = '
  select entrance_date, ' + @doorCode2 + '
  from (
    select 
      CONVERT(date,substring(entrance_date,0,9)) as [entrance_date],  [door_code], [pass_id]
      from dbo.entrance_history
      where door_code in ('+ @doorCode +')
      group by CONVERT(date,substring(entrance_date,0,9)), [door_code], [pass_id]
  ) as [base_table]
  pivot (
    count([pass_id]) 
    for [door_code] in ('+ @doorCode2 +')
  ) as [pvt] 
  order by entrance_date desc
'
exec sp_executesql @sql

И это возвращает нужный мне набор данных.

entrance_date|000A|000B|000C
2018-03-13   |9   |4   |1
2018-03-12   |23  |1   |1
2018-03-11   |18  |1   |1
2018-03-10   |19  |1   |1
0
ringord 14 Мар 2018 в 02:23

Проверьте этот запрос. Я считаю, что одной группировки достаточно

declare @doorCode nvarchar(Max) = '''000A'',''000B'',''000C'''
declare @doorCode2 nvarchar(Max) = '[000A],[000B],[000C]'
declare @sql nvarchar(Max);

set @sql = '
    select
        entrance_date, ' + @doorCode2 + '
    from (
        select 
            CONVERT(date,substring(entrance_date,0,9)) as [entrance_date], count([pass_id]) as [entrance_count], [door_code]
        from 
            dbo.entrance_history
        where 
            door_code in (' + @doorCode + ')
            group by CONVERT(date,substring(entrance_date,0,9)), [door_code]
    ) as [base_table]
    pivot (
        max([entrance_count]) for [door_code] in (' + @doorCode2 + ')
    ) as pvt
    '
exec sp_executesql @sql
0
uzi 13 Мар 2018 в 09:03