2015-10-29 1 views
1

Quelle est la syntaxe correcte pour écrire une fonction d'agrégat en utilisant over (partition by)?SQL Server 2012: distinct avec clause over dans une fonction d'agrégat

Ou comment cela pourrait-il être réécrit? Je n'ai pas de tableau d'échantillons, car je fais cela comme un exercice pour moi-même. Je me demande si ce serait possible. Veuillez trouver ci-dessous le scénario auquel je pensais.

Prenons un exemple simple comme échantillon:

select 
    *, 
    sum (column1 * column2) over (partition by column10, colum12)/100 as sumProduct 
into #myTemp 
from myTable 

La requête ci-dessus fonctionne sur une table qui a ces colonnes. Maintenant, comment pourrais-je écrire la même chose pour des valeurs distinctes de column1 et column2?

La requête ci-dessous ne fonctionne pas mais c'est le pseudo pour ce que j'essaie d'obtenir.

Le résultat attendu est assez simple (voir distinct column1 * distinct column2)

select 
    *, 
    sum (distinct column1 * distinct column2) over (partition by column10, colum12)/100 as sumProduct 
into #myTemp 
from myTable 

EDIT: Je veux éviter group by. J'essaie d'utiliser la partition autant que possible afin d'améliorer les fonctions de la fenêtre

+1

Vous ne pouvez pas vous distinct dans la fonction de Windows. Commencez par faire une distinction avant d'appliquer votre fonction. –

+0

Les fonctions d'agrégation ou de fenêtre - à l'exception de 'COUNT()' - ne doivent pas utiliser 'DISTINCT'. –

Répondre

2

L'utilisation de distinct avec une agrégation autre que count() est généralement incorrecte. Cela est aussi vrai pour les fonctions de fenêtre que pour les fonctions d'agrégation.

Vous pouvez faire l'équivalent de count(distinct) en utilisant row_number() et agrégation conditionnelle:

select t.*, 
     sum(case when seqnum = 1 then 1 else 0 end) as CountDistinct 
into #myTemp 
from (select t.*, 
      row_number() over (partition by column10, colum12 order by (select NULL)) as seqnum 
     from myTable t 
    ) t; 

EDIT:

Le comptera au-dessus d'une valeur NULL comme une valeur "valide", à la différence COUNT(DISTINCT). Ceci est facilement remédié:

select t.*, 
     count(case when seqnum = 1 then colum12 end) as CountDistinct 
into #myTemp 
from (select t.*, 
      row_number() over (partition by column10, colum12 order by (select NULL)) as seqnum 
     from myTable t 
    ) t; 
+0

Est-ce que cela fonctionnera aussi si, disons, une valeur de 'column' ou' column2' est/sera 'NULL'? Grande réponse – CM2K

+0

@ CM2K. . . Ceci traite NULL légèrement différemment car il le compte comme une valeur valide. J'ai ajouté une version qui est cohérente, même pour les valeurs 'NULL'. –

+0

Je suis un débutant avec 'CTE' et' row_number() '(pour être honnête, seulement lire brièvement à leur sujet ne les a jamais utilisés). Je comprends la logique ici (ou, au moins j'espère), mais comment calculer/incorporer 'sumProduct' comme montré dans la question dans votre requête? – CM2K