2017-02-03 5 views
3

Я пытаюсь объединить несколько таблиц вместе. Одна из таблиц, к которой я пытаюсь присоединиться, содержит сотни строк на идентификатор данных. Я пытаюсь повернуть около 100 строк для каждого идентификатора в столбцы. Значение, которое я пытаюсь использовать, не всегда находится в одной строке. Ниже приведен пример (у моей реальной таблицы есть сотни строк на ID). AccNum, например, в ID 1, может быть в столбце NumV, но для ID 2 он может находиться в столбце CharV.более эффективно свернуть строки

ID QType  CharV  NumV 
1 AccNum     10 
1 EmpNam  John Inc 0 
1 UW   Josh  0 
2 AccNum  11 
2 EmpNam  CBS   0 
2 UW   Dan   0 

оригинальный код, который я использовал, был оператор выбора с сотнями линий, как один ниже:

Max(Case When PM.[QType] = 'AccNum' Then NumV End) as AccNum 

Этот код с сотнями на линиях завершена в чуть менее 10 мин. Однако проблема заключается в том, что только вытягивает значения из указанного столбца, поэтому я всегда буду потерять данные, находящиеся в другом столбце. (В приведенном выше примере я бы получил AccNum 10, но не AccNum11, потому что он находится в столбце CharV).

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

;with CTE 
As 
(
    Select [PMID], [QType], 
     Value=concat(Nullif([CharV],''''),Nullif([NumV],0)) 
     From [DBase].[dbo].[PM] 
) 

Select C.[ID] AS M_ID 
    ,Max(c.[AccNum]) As AcctNum 
    ,Max(c.[EmpNam]) As EmpName 

и так далее ...

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

from CTE 
pivot (max(Value) for [QType] in ([AccNum],[EmpNam],(more rows)))As c 

Проблема с этим кодом состоит в том, что для запуска требуется почти 2 часа.

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

+0

Предположительно (вы можете проверить, хотя) это стержень, который берет время, а не КТР однако я ожидаю, что вы можете упростить Value = строку в КТР с COALESCE ([CharV], [NumV], 0), см., если это имеет какой-либо эффект. – Rikalous

+0

К сожалению, это не сработает, потому что ни одно из полей не является истинным. Если CharV не имеет значения, то это пустая строка «», и если NumV не имеет значения, то это просто 0. –

ответ

2

Возможно, вы можете уменьшить Concat/NullIf обработку не используя UNION ALL

Select ID,QType,Value=CharV From @YourTable where CharV>'' 
Union All 
Select ID,QType,Value=cast(NumV as varchar(25)) From @YourTable where NumV>0 

Для условной агрегации подход

Нет необходимости беспокоиться о том, какое поле, просто эталонное значение

Select [ID] 
     ,[Accnum] = Max(Case When [QType] = 'AccNum' Then Value End) 
     ,[EmpNam] = Max(Case When [QType] = 'EmpNam' Then Value End) 
     ,[UW]  = Max(Case When [QType] = 'UW'  Then Value End) 
From (
     Select ID,QType,Value=CharV From @YourTable where CharV>'' 
     Union All 
     Select ID,QType,Value=cast(NumV as varchar(25)) From @YourTable where NumV>0 
    ) A 
Group By ID 

Для подхода PIVOT

Select [ID],[AccNum],[EmpNam],[UW] 
From (
     Select ID,QType,Value=CharV From @YourTable where CharV>'' 
     Union All 
     Select ID,QType,Value=cast(NumV as varchar(25)) From @YourTable where NumV>0 
    ) A 
Pivot (max([Value]) For [QType] in ([AccNum],[EmpNam],[UW])) p 
+0

Для этого подхода Союз All будет внутри CTE, или это для оператора select после? –

+0

@VBA_SQL_Programmer Я видел, как производительность страдает от больших CTE. См. Обновленный ответ для двух подходов. –

+0

@VBA_SQL_Программист. У меня нет никакого смысла, как могут быть строки, с которыми вы имеете дело, но нет НИКАКИХ ШАГОВ В ТАБЛИЦЕ TEMP –