Запрос перекрестной таблицы в SQL, который сравнивает и добавляет столбцы

#sql #sql-server #crosstab

#sql #sql-server #перекрестная таблица

Вопрос:

У меня есть таблица в sql server, которая содержит три столбца: «дата», «полдень» и «3 часа дня». Первый столбец не требует пояснений, но последние два содержат имена приглашенных докладчиков в месте проведения в соответствии со временем их прибытия. Я хочу написать запрос с перекрестными вкладками, который записывает имена докладчиков в заголовок столбца и подсчитывает, сколько раз этот докладчик выступал в эту дату.

Пример

 Date   | Noon   |  3pm
092916 | Tom    | <null>
092816 | Dick   |  Tom 
092716 | <null> |  Suzy 
  

Желаемый результат

 Date   | Dick   |  Tom   |  Suzy
092916 | <null> |   1    | <null> 
092816 |  1     |   1    | <null>
092716 | <null> | <null> |   1
  

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

Комментарии:

1. Слово, которое вы ищете, это pivot

Ответ №1:

вы можете создавать свой запрос динамически.

это создаст оператор count (case) для каждого имени, найденного в столбце noon или 3pm.. аналогично COUNT(CASE WHEN 'Dick' IN ([Noon],[3pm]) THEN 1 END) as [Dick]

 DECLARE @speakers NVARCHAR(MAX),
        @sql NVARCHAR(MAX)

SET @speakers = STUFF((
    SELECT  ',COUNT(CASE WHEN '''   [Name]   ''' IN ([Noon],[3pm]) THEN 1 END) as '   QUOTENAME([Name])
    FROM    (SELECT [Noon] AS [Name] FROM Table1
             UNION ALL SELECT [3pm] FROM Table1) t
    GROUP BY t.Name 
    FOR XML PATH('')
), 1, 1, '')

SET @sql = N'SELECT Date, '   @speakers   ' FROM Table1 GROUP BY Date'

--Print @sql to see what's going on
EXEC(@sql)
  

Ответ №2:

Вы могли бы использовать этот запрос:

 select *
from   (
        select   date, noon as speaker, count(*) as times
        from     events
        group by date, noon
        union all 
        select   date, [3pm], count(*)
        from     events
        group by date, [3pm]
       ) as u
pivot  (
        sum(times)
        for speaker in ([Dick], [Tom], [Suzy])
       ) as piv
order by date desc;
  

… который дает вам количество для каждой ячейки (null, 1 или 2):

 Date   | Dick   |  Tom   |  Suzy
092916 | <null> |   1    | <null> 
092816 |   1    |   1    | <null>
092716 | <null> | <null> |   1
  

Комментарии:

1. Спасибо за ваш ответ. Мне действительно нужен подсчет, поскольку некоторые докладчики выступают дважды в один и тот же день. У меня также есть что-то вроде 50 динамиков за 5-летний период, некоторые из которых уникальны для своего временного интервала, что усложняет объединение, поскольку существуют разные столбцы, если вы поворачиваете каждый временной интервал по отдельности.

2. Хорошо, я обновил запрос для подсчета. group by Предложения необходимы, когда несколько записей могут иметь одну и ту же дату. Если в этом нет необходимости, вы можете при необходимости удалить их и заменить count(*) на 1 . Но если у вас неизвестное количество выступающих, я бы посоветовал вам использовать возможности вашей среды программирования. Это больше подходит для этого.