SOMAR SOBRE A PARTIÇÃO POR
esta consulta está a devolver dados duplicados vezes sem conta. A contagem é correta para um total completo, mas eu estou esperando uma linha, e ainda estou recebendo o valor repetido cerca de 40 vezes. Alguma ideia?
SELECT BrandId
,SUM(ICount) OVER (PARTITION BY BrandId )
FROM Table
WHERE DateId = 20130618
Já percebi?
BrandId ICount
2 421762
2 421762
2 421762
2 421762
2 421762
2 421762
2 421762
1 133346
1 133346
1 133346
1 133346
1 133346
1 133346
1 133346
O que me está a escapar?
não posso remover a partição porque toda a consulta é assim:
SELECT BrandId
,SUM(ICount) OVER (PARTITION BY BrandId)
,TotalICount= SUM(ICount) OVER ()
,SUM(ICount) OVER () / SUM(ICount) OVER (PARTITION BY BrandId) as Percentage
FROM Table
WHERE DateId = 20130618
que devolve isto:
BrandId (No column name) TotalICount Percentage
2 421762 32239892 76
2 421762 32239892 76
2 421762 32239892 76
2 421762 32239892 76
2 421762 32239892 76
2 421762 32239892 76
Eu esperaria uma saída como esta sem ... ter de utilizar um método distinto:
BrandId (No column name) TotalICount Percentage
2 421762 32239892 76
9 1238442 32239892 26
10 1467473 32239892 21
4 answers
Podias ter usado DISTINCT
ou apenas remover as porções PARTITION BY
e usar GROUP BY
:
SELECT BrandId
,SUM(ICount)
,TotalICount = SUM(ICount) OVER ()
,Percentage = SUM(ICount) OVER ()*1.0 / SUM(ICount)
FROM Table
WHERE DateId = 20130618
GROUP BY BrandID
Não sei por que você está dividindo o total pela contagem por brand, se isso é um erro e você quer por cento do total, em seguida, reverter esses bits acima para:
SELECT BrandId
,SUM(ICount)
,TotalICount = SUM(ICount) OVER ()
,Percentage = SUM(ICount)*1.0 / SUM(ICount) OVER ()
FROM Table
WHERE DateId = 20130618
GROUP BY BrandID
Na minha opinião, acho que é importante explicar o por quepor trás da necessidade de um grupo no seu SQL ao somar com a cláusula sobre() e por que Você está recebendo linhas repetidas de dados quando você está esperando uma linha por brand.
Tome este exemplo: você precisa agregar o preço total de venda de cada linha de ordem, por categoria de ordem específica, entre duas datas, mas você também precisa manter os dados de ordem individual em seus resultados finais. Um montante() sobre o preço de venda a coluna não lhe permitiria obter os totais correctos porque exigiria um grupo, pelo que esmagaria os detalhes porque não seria capaz de manter as linhas de encomendas individuais na instrução select.
Muitas vezes vemos uma tabela #temp, variável @table, ou CTE preenchido com a soma de nossos dados e agrupados para que possamos juntar-nos a ele novamente mais tarde para obter uma coluna das somas que precisamos. Isto pode adicionar tempo de processamento e linhas extras de código. Em vez disso, use o OVER (partição por () como isto:
SELECT
OrderLine,
OrderDateTime,
SalePrice,
OrderCategory,
SUM(SalePrice) OVER(PARTITION BY OrderCategory) AS SaleTotalPerCategory
FROM tblSales
WHERE OrderDateTime BETWEEN @StartDate AND @EndDate
Repare que não estamos a agrupar e temos a coluna de linhas de ordem individual seleccionada. A partição por na última coluna nos devolverá um total de preço de venda para cada linha de dados em cada categoria. O que a última coluna, essencialmente, diz que é, queremos que o soma do preço de venda (SOMA(SalePrice)) sobre um partição dos meus resultados e por especificado categoria (MAIS(PARTIÇÃO CategoryHere) .
Se removermos as outras colunas da nossa instrução seleccionada, e deixarmos a nossa coluna de soma final (), como esta:
SELECT
SUM(SalePrice) OVER(PARTITION BY OrderCategory) AS SaleTotalPerCategory
FROM tblSales
WHERE OrderDateTime BETWEEN @StartDate AND @EndDate
Os resultados continuarão a repetir esta soma para cada linha do nosso conjunto de resultados original. A razão é que este método não requer um grupo por. Se você não precisa reter dados de linha individuais, então simplesmente somar () sem o uso de OVER() e agrupar seus dados apropriadamente. Mais uma vez, se você precisar de uma coluna adicional com totais específicos, você pode usar o método OVER (partição por ()) descrito acima sem seleção adicional para se juntar de volta.
O acima é puramente para explicar por que ele está recebendo linhas repetidas do mesmo número e para ajudar a entender o que esta cláusula prevê. Este método pode ser usado de muitas maneiras e eu encorajo muito mais a leitura da documentação aqui:
Remover partition by
e adicionar group by
Cláusula,
SELECT BrandId
,SUM(ICount) totalSum
FROM Table
WHERE DateId = 20130618
GROUP BY BrandId
Acho que a pergunta que queres é esta:
SELECT BrandId, SUM(ICount),
SUM(sum(ICount)) over () as TotalCount,
100.0 * SUM(ICount) / SUM(sum(Icount)) over () as Percentage
FROM Table
WHERE DateId = 20130618
group by BrandId;
Isto faz o group by
para a marca. E calcula a "percentagem". Esta versão deve produzir um número entre 0 e 100.