2010-09-29 14 views
1

J'ai récemment exécuté le cas suivant à plusieurs reprises, soit j'ai besoin d'appliquer MAX() ou SUM() à une colonne sur une table, mais j'ai besoin des ensembles de valeurs DISTINCT pour les autres colonnes. Par exemple, considérons le tableau suivant et les colonnes associées représentant les détails d'une connexion à StackOverflow.Comment combiner les fonctions d'agrégat sql avec distinctement plus proprement?

SoUserLogins (OpenIdToken, Nom, IpAdress, LoginTimeStamp, QuestionsAsked)

je pourrais avoir besoin d'un jeu de résultats contenant les utilisateurs et leur dernière connexion.

SELECT DISTINCT 
    OpenIdToken, 
    MAX(LoginTimeStamp) 
INTO #tmpLastLogin 
FROM SoUserLogins 
GROUP BY OpenIdToken 

Mais j'ai besoin de valeurs distinctes des autres colonnes. Je vais envelopper dans une expression de table commune (CTE) parce que je vais l'utiliser plus tard et je ne veux pas avoir à nettoyer une autre table temporaire.

;WITH tmpLastLogin_CTE AS (
SELECT DISTINCT 
    SOL.OpenIdToken, SOL.Name, SOL.IpAdress, SOL.QuestionsAsked 
    TTL.LastLogin 
FROM SoUserLogins SOL 
JOIN #tmpLastLogin TLL ON SOL.OpenIdToken = TLL.OpenIdToken 
) 
--Extra SQL using tmpLastLogin_CTE goes here 

Vous pouvez changer le MAX (LoginTimeStamp) à SUM (QuestionsAsked) dans le code ci-dessus avec quelques modifications supplémentaires pour voir un exemple similaire.

Ma question, y a-t-il une manière plus propre ou plus élégante de faire face à ces situations? J'utilise SQL Server.

+0

Je suggère de retirer le mot-clé DISTINCT de la première requête, car il est redondant et déroutant - la clause GROUP BY garantit que seules les valeurs distinctes de OpenIdToken seront retournés . –

Répondre

7

Voulez-vous dire cela?

SELECT DISTINCT 
    SOL.OpenIdToken, SOL.Name, SOL.IpAdress, SOL.QuestionsAsked, 
    MAX(LoginTimeStamp) OVER (PARTITION BY OpenIdToken) AS LastLogin 
FROM SoUserLogins SOL 

Ainsi, vous aurez plusieurs lignes par OpenIdToken et la même valeur LastLogin sera répétée pour toutes les lignes au sein d'un groupe?

+0

Je pense que c'est probablement la façon dont je veux aller. Je pensais que cela ne fonctionnerait pas avec Partition By sur plusieurs colonnes, c'est-à-dire (Partition par OpenIdToken, IpAddress), mais je me suis heureusement trompé. –

0

Si vous êtes sous Oracle Database vous devriez envisager d'utiliser personnalisée * Oracle Fonction analytique * qui vous permettent de agreggate vos données en ligne selon une colonne. En écrivant ceci, Martin a répondu.

Mais une documentation n'a pu être trouvée here (en français)

+0

Je pense que Thomas utilise une version de SQLServer, basée sur l'insertion dans la table temporaire. Je comprends que les versions plus récentes de SQLServer ont des fonctions analytiques similaires. –

+1

J'utilise SQL Server. Je vais mettre à jour la question pour refléter cela. –

+1

@Mark - Oui. Si l'OP est sur une version de SQL Server qui prend en charge les CTE (2005+), ils seront également sur une version qui prend en charge ces fonctions. –