Eu defini function
com table value parameter
qual returns
median
conforme os valores passados para ele. Function
definido como:
CREATE FUNCTION [dbo].[fn_GetMedian](@List TypeMedian READONLY)
RETURNS INT
AS
BEGIN
<function body>
END
E Table Type
TypeMedian
definição como:
CREATE TYPE [dbo].[TypeMedian] AS TABLE(
[VALUE] [int] NULL
)
Agora eu tenho um table
Listing
com valores preenchidos nele como e table
RESULT
a ser preenchido de acordo com table
Listing
:
Tables structure
Como
LISTING(ListingCol1,ListingCol2,ListingCol3,ListingCol4,ListingCol5)
RESULT(Col1,Col2,Col3,Col4,Col5)
A tabela de listagem tem mais de 1.000 linhas de dados.
Todos column
de ambos tables
são do tipo int
. Agora eu quero preencher columns
e RESULT table
isso column
pode ser calculado como:
Col1 = SUM(ListingCol1)
Col2 = SUM(ListingCol2)
Col3 = dbo.fn_GetMedian(ListingCol3)
Col4 = dbo.fn_GetMedian(ListingCol4)
Col5 = dbo.fn_GetMedain(ListingCol5)
E estou fazendo assim:
INSERT INTO RESULT(Col1)
SELECT SUM(ListingCol1)
Update RESULT
SET Col2 = SUM(ListingCol2)
DECLARE @tbl_Median TypeMedian
INSERT INTO @tbl_Median
SELECT ListingCol3
FROM Listing
UPDATE RESULT
SET Col3 = dbo.fn_GetMedian(@tbl_Median)
-- For next column
DELETE FROM @tbl_Median
INSERT INTO @tbl_Median
SELECT ListingCol4
FROM Listing
UPDATE RESULT
SET Col4 = dbo.fn_GetMedian(@tbl_Median);
--E esta consulta de atualização é repetida para as colunas restantes. Como eu poderia fazer isso em uma única consulta?
Para duas somas e três medianas, em uma única tabela, honestamente não consigo ver o benefício de usar uma solução dinâmica ou baseada em função complicada.
É muito fácil construir uma única consulta usando o método mediano de Peter Larsson que mostrei antes :
Solução
Formato do plano de execução esperado:
Deixando de lado as implicações de desempenho por um momento, a maneira mais fácil de fazer isso em uma única consulta ** é criando um agregado definido pelo usuário (UDA) via SQLCLR. Isto é o que eu descrevi em minha resposta à sua pergunta relacionada:
Como posso passar coluna para função no sql?
Se você tivesse essa função, poderia fazer o seguinte:
Com isso dito, o desempenho ainda é algo que precisa ser considerado. A abordagem mostrada acima não funciona em todas as situações. Se a
LISTING
tabela tiver milhões de linhas (pelo menos milhões por cada agrupamento), isso pode não funcionar. Mas se cada agrupamento tiver 5.000 linhas, ou talvez até 10.000 ou algo assim, e o processo não for executado várias vezes por minuto, você ficará bem. Claro, como com qualquer coisa, deve ser testado contra seus dados reais para determinar se há um problema de desempenho ou não.** Por "maneira mais fácil em uma única consulta", estou assumindo que o método desejado é aquele que pode ser facilmente aplicado em várias situações, principalmente em consultas ad hoc.