SQL строк в столбцы, PIVOT, вероятно, будет работать, но не уверен, как с несколькими столбцами - PullRequest
1 голос
/ 19 июля 2011

У меня плохо спроектированная таблица, в которой есть смесь строк и столбцов, где, вероятно, следовало бы иметь 1 строку со множеством столбцов или какой-то другой дизайн целиком. Но эта ошибка была 20 лет назад, на чужих часах.

Прямо сейчас я достигаю той цели, которую хочу, множеством самосоединений. Это мучительно медленно.

Следующее настроит меня как сейчас:

declare @client table
(
    clientNumber int,
    name    varchar(10)
)

insert into @client values (1, 'Bob');
insert into @client values (2, 'Alice');

declare @options table
(
    clientNumber int,
    optionKey varchar(4),
    optionValue1 int,
    optionValue2 int,
    optionValue3 int
)
insert into @options values (1, 'optA', 1, 1, 0);
insert into @options values (1, 'optB', 0, 1, 0);
insert into @options values (2, 'optA', 1, 1, 1);
insert into @options values (2, 'optC', 0, 0, 1);

select c.clientNumber, c.name, 
        oA.optionValue1 as [Graduated], 
        oA.optionValue2 as [Employed], 
        oA.optionValue3 as [Married], 
        oB.optionValue1 as [HasPets], 
        oB.optionValue2 as [LikesThai], 
        oB.optionValue3 as [MathWiz], 
        oC.optionValue1 as [DrvLicense], 
        oC.optionValue2 as [Registered], 
        oC.optionValue3 as [Outdoorsy] 
    from @client c
    left outer join @options oA 
        on oA.clientNumber = c.clientNumber and oA.optionKey = 'optA'
    left outer join @options oB 
        on oB.clientNumber = c.clientNumber and oB.optionKey = 'optB'
    left outer join @options oC 
        on oC.clientNumber = c.clientNumber and oC.optionKey = 'optC'

Для этих результатов:

result set from above query

Набор результатов - именно то, что я хочу. Не у каждого клиента есть запись A, B или C, поэтому null в наборе результатов в порядке. Я не могу найти подобный пример через некоторое время поиска, поэтому я не уверен, что PIVOT действительно то, что я ищу. Предложения?

Обновление: похоже, это дает те же результаты. Я собираюсь проверить его на более крупном случае, чтобы увидеть, быстрее ли он, чем все самостоятельные соединения. (Я подозреваю, что это так). Я все еще хотел бы знать, не лает ли я не тем деревом с помощью шарниров.

select clientNumber,
    Min(Case o.optionKey when 'optA' then o.optionValue1 end) [Graduated],
    Min(Case o.optionKey when 'optA' then o.optionValue2 end) [Employed],
    Min(Case o.optionKey when 'optA' then o.optionValue3 end) [Married],
    Min(Case o.optionKey when 'optB' then o.optionValue1 end) [HasPets],
    Min(Case o.optionKey when 'optB' then o.optionValue2 end) [LikesThai],
    Min(Case o.optionKey when 'optB' then o.optionValue3 end) [MathWix],
    Min(Case o.optionKey when 'optC' then o.optionValue1 end) [DrvLicense],
    Min(Case o.optionKey when 'optC' then o.optionValue2 end) [Registered],
    Min(Case o.optionKey when 'optC' then o.optionValue3 end) [Outdoorsy]
    from @options o
    group by clientnumber

Ответы [ 2 ]

2 голосов
/ 19 июля 2011

Вот несколько вариантов.Оба решения используют технику, которая разворачивает данные.Первое решение изменит ваши NULL на 0.

SELECT c.clientNumber, c.name, 
    MAX(CASE WHEN o.optionKey = 'optA' THEN o.optionValue1 ELSE 0 END) AS [Graduated], 
    MAX(CASE WHEN o.optionKey = 'optA' THEN o.optionValue2 ELSE 0 END) AS [Employed], 
    MAX(CASE WHEN o.optionKey = 'optA' THEN o.optionValue3 ELSE 0 END) AS [Married], 
    MAX(CASE WHEN o.optionKey = 'optB' THEN o.optionValue1 ELSE 0 END) AS [HasPets], 
    MAX(CASE WHEN o.optionKey = 'optB' THEN o.optionValue2 ELSE 0 END) AS [LikesThai], 
    MAX(CASE WHEN o.optionKey = 'optB' THEN o.optionValue3 ELSE 0 END) AS [MathWiz], 
    MAX(CASE WHEN o.optionKey = 'optC' THEN o.optionValue1 ELSE 0 END) AS [DrvLicense], 
    MAX(CASE WHEN o.optionKey = 'optC' THEN o.optionValue2 ELSE 0 END) AS [Registered], 
    MAX(CASE WHEN o.optionKey = 'optC' THEN o.optionValue3 ELSE 0 END) AS [Outdoorsy] 
FROM @client c
LEFT OUTER JOIN @options o 
    ON o.clientNumber = c.clientNumber
GROUP BY c.clientNumber, c.name
ORDER BY c.clientNumber, c.name

Второе решение сохраняет значения NULL.Однако требуется явное преобразование типов из BIT в TINYINT, поскольку функция MAX не выполняется для типов данных BIT.

0 голосов
/ 19 июля 2011

Я не уверен насчет его производительности, но я бы сделал это так:

select c.clientNumber, c.name, 
    oA.optionValue1 as [Graduated], 
    oA.optionValue2 as [Employed], 
    oA.optionValue3 as [Married], 
    oB.optionValue1 as [HasPets], 
    oB.optionValue2 as [LikesThai], 
    oB.optionValue3 as [MathWiz], 
    oC.optionValue1 as [DrvLicense], 
    oC.optionValue2 as [Registered], 
    oC.optionValue3 as [Outdoorsy] 
from @client c 
     OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optA' And clientnumber = c.clientnumber) oA
     OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optB' And clientnumber = c.clientnumber) oB
     OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optC' And clientnumber = c.clientnumber) oC

или CTE может быть полезным

with t as
(select oA.ClientNumber, 
    oA.optionValue1 as [Graduated], 
    oA.optionValue2 as [Employed], 
    oA.optionValue3 as [Married], 
    oB.optionValue1 as [HasPets], 
    oB.optionValue2 as [LikesThai], 
    oB.optionValue3 as [MathWiz], 
    oC.optionValue1 as [DrvLicense], 
    oC.optionValue2 as [Registered], 
    oC.optionValue3 as [Outdoorsy] 
from 
     (SELECT * FROM @options WHERE optionkey = 'optA') oA
     OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optB' And clientnumber = oA.clientnumber) oB
     OUTER APPLY (SELECT * FROM @options WHERE optionkey = 'optC' And clientnumber = oA.clientnumber) oC )

 select c.clientNumber, c.name,
    t.[Graduated], 
    t.[Employed], 
    t.[Married], 
    t.[HasPets], 
    t.[LikesThai], 
    t.[MathWiz], 
    t.[DrvLicense], 
    t.[Registered], 
    t.[Outdoorsy] 
from @client c join t on c.clientnumber = t.clientnumber
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...