Сводная таблица SQL не помещает результаты в одну строку - PullRequest
1 голос
/ 26 марта 2019

Я пытаюсь создать сводную таблицу в SQL.Мои результаты не сводятся в одну строку на TID, как я надеялся.Этот пример должен прояснить мою проблему:

    Results:

    TID NS_AM   AS_AM   NS_DB   AS_DB
    TID 1a  971     947     
    TID 2   807     974     
    TID 1a                  954     910
    TID 2                   931     904


    Desired Results:

    TID     NS_AM   AS_AM   NS_DB   AS_DB
    TID 1a  971     947     954     910
    TID 2   807     974     931     904 

РЕДАКТИРОВАТЬ: Это происходит из большого динамического запроса.Я не мог вставить этот запрос, потому что это сделало бы вопрос действительно запутанным.Я должен использовать Pivot / Unpivot.

Любая помощь будет принята с благодарностью.Ниже приведены примеры данных и запрос, который сгенерировал мои результаты.

Как видите, элементы AM объединяются в одну строку, а элементы DB объединяются в одну строку, но они не сообщают обо всех результатах, как я надеялся.

            drop table if exists  mock_data;
             create table MOCK_DATA (
                tid VARCHAR(50),
                plantype VARCHAR(50),
                ns VARCHAR(50),
                [as] VARCHAR(50)
            );
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '112', '048');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '142', '889');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '887', '668');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '093', '910');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '954', '266');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '822', '201');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '234', '083');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '527', '716');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '662', '168');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '795', '947');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '971', '588');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '755', '234');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '199', '603');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '164', '362');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '943', '462');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '971', '164');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '594', '822');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '467', '478');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '064', '591');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '639', '298');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '186', '797');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '226', '369');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '036', '272');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '807', '197');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '167', '402');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '477', '047');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '262', '974');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '268', '282');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '508', '069');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '303', '528');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '747', '325');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '293', '614');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '886', '221');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '652', '365');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '931', '904');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '089', '662');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '922', '497');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '722', '328');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '386', '324');
            insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '402', '552');



            SELECT [TID],
                   IsNull([NS_AM], '') AS [NS_AM],
                   IsNull([AS_AM], '') AS [AS_AM] 
            FROM
            (
                SELECT [TID],
                       [PlanType],
                       col+'_'+CAST(PlanType AS VARCHAR(50)) col,
                       value
                FROM
            (
                SELECT PlanType,
                       [TID],
                       CAST(NS AS VARCHAR(100)) AS NS,
                       CAST(AS AS VARCHAR(100)) AS AS 

                FROM #temp
            ) s UNPIVOT(value FOR col IN(NS,
                                         AS )) unpiv
            ) src PIVOT(MAX(value) FOR col IN([NS_AM],
                                              [AS_AM], 
                                              [NS_DB],
                                              [AS_DB] 

             )) p; 

Большое спасибо заранее.

Ответы [ 5 ]

2 голосов
/ 26 марта 2019

Это может быть очень просто, используя CROSS TABS вместо того, чтобы разворачивать и поворачивать данные.

SELECT TID, 
       MAX( CASE WHEN PlanType = 'AM' THEN [ns] END) AS NS_AM,
       MAX( CASE WHEN PlanType = 'AM' THEN [as] END) AS AS_AM,
       MAX( CASE WHEN PlanType = 'DB' THEN [ns] END) AS NS_DB,
       MAX( CASE WHEN PlanType = 'DB' THEN [as] END) AS AS_DB
FROM MOCK_DATA
GROUP BY TID;

Если вы хотите использовать динамический код, его не так сложно конвертировать. Это просто становится проблемой копирования-вставки-редактирования для каждого столбца, который вам нужно обработать, и код добавит столько значений для plantype, сколько необходимо.

DECLARE @SQL nvarchar(MAX)

SELECT @SQL = N'SELECT TID' + CHAR(10) 
            + ( SELECT DISTINCT REPLACE( REPLACE(
                        CHAR(9) + ',MAX( CASE WHEN PlanType = <<quotedplantype>> THEN [ns] END) AS NS_<<plantype>>' + CHAR(10)
                      + CHAR(9) + ',MAX( CASE WHEN PlanType = <<quotedplantype>> THEN [as] END) AS AS_<<plantype>>' + CHAR(10)
                        , '<<quotedplantype>>', QUOTENAME(plantype, '''')), '<<plantype>>', plantype)
            FROM MOCK_DATA
            FOR XML PATH(''), TYPE).value('./text()[1]', 'varchar(max)') + 
           + N'FROM MOCK_DATA' + NCHAR(10)
           + N'GROUP BY TID;'

EXEC sp_executesql @SQL /*, @params_def, @param1, @param2,..., @paramN*/;
1 голос
/ 27 марта 2019

Вот динамическое решение, как было обещано, с использованием курсоров, а не объединений Он динамически добавляет столбцы в финальную таблицу и обновляет данные внутри цикла курсора

IF EXISTS(SELECT 1 FROM sysobjects where name='myMOCK_DATA') drop table myMOCK_DATA
create table myMOCK_DATA (tid varchar(10));insert into  myMOCK_DATA(tid) select distinct(tid) from MOCK_DATA
declare mycursor cursor for
select tid,plantype,max(ns)[m_ns],max([as])[m_as] from MOCK_DATA group by tid,plantype
declare @plantype as varchar(2);declare @tid as varchar(10);declare @m_ns as int;declare @m_as as int
declare @script as varchar(max);open mycursor
fetch mycursor into @tid,@plantype,@m_ns,@m_as
while @@fetch_status=0
begin
set @script='IF not EXISTS(SELECT 1 FROM sys.columns  WHERE Name = ''NS_'+@plantype +''' AND Object_ID = Object_ID(N''myMOCK_DATA''))
BEGIN
    alter table myMOCK_DATA add NS_'+@plantype +' integer
END'
print @script;exec(@script)
set @script='IF not EXISTS(SELECT 1 FROM sys.columns 
          WHERE Name = ''AS_'+@plantype + ''' AND Object_ID = Object_ID(N''myMOCK_DATA''))
BEGIN
    alter table myMOCK_DATA add AS_'+@plantype +' integer
END'
print @script;exec(@script)
set @script='update myMOCK_DATA set NS_'+@plantype+'='+convert(varchar(10),@m_ns)+ ' where tid='''+@tid+''''
print @script;exec(@script)
set @script='update myMOCK_DATA set AS_'+@plantype+'='+convert(varchar(10),@m_as)+ ' where tid='''+@tid+''''
print @script;exec(@script)
fetch mycursor into @tid,@plantype,@m_ns,@m_as
end
close mycursor
deallocate mycursor
select * from myMOCK_DATA

enter image description here

1 голос
/ 26 марта 2019

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

select v1.tid,v1.m_ns[Ns_Am],v1.m_as[As_Am],v2.m_ns[NS_DB],V2.m_As[AS_DB] from(
select tid,plantype,max(ns)[m_ns],max([as]) [m_as]  from MOCK_DATA group by tid,plantype) v1
inner join
(select tid,plantype,max(ns)[m_ns],max([as]) [m_as]  from MOCK_DATA group by tid,plantype)v2
on v1.tid=v2.tid and v1.plantype='Am' and  v2.plantype='DB' 

enter image description here

Вы также можете использовать этот скрипткоторый вы можете сделать динамическим (дай мне немного времени, я сделаю это для тебя!)

select v1.tid,v1.[am] [ns_am],v1.[db][ns_db],v2.[am] [as_am],v2.[db][as_db] from
(select * from(
select tid,ns,[PlanType] from MOCK_DATA) s
pivot
(max(ns) for [PlanType] in ([AM],[DB])  )s
) v1
inner join
(
select * from(
select tid,[as],[PlanType] from MOCK_DATA) s
pivot
(max([as]) for [PlanType] in ([AM],[DB])  )s) v2

on v1.tid=v2.tid
1 голос
/ 26 марта 2019

Попробуйте добавить «Order by TID» в выражения PIVOT / UNPIVOT.

1 голос
/ 26 марта 2019

Null используется в качестве замены (как большое случайное число для некоторого пропущенного значения), поэтому его так уникально.Но здесь, поскольку агрегатные функции игнорируют нули, за исключением подсчета в соответствии со стандартом, хотя вы можете также проверить, используя как min, так и max

. Вы можете получить group by и взять min/max, если по моему предположениюtheres только нулевые значения, отличающиеся как выше

  Select TID, min(NS_AM),  min( AS_AM),   
   min(NS_DB),  min(AS_DB) Group by 
    TID.     
...