2017-02-08 1 views
1

J'ai une table SQL avec trois champs Id, Player, ColorNumber. L'identifiant n'est pas une clé primaire et peut être répété. Voici le tableau comme suit:MS procédure stockée sql agréger des données basées sur certaines conditions

enter image description here

Je veux l'utiliser pour créer une table Capitaines, par exemple. Mais le capitaine doit être sélectionné sur les occurrences maximales d'un joueur pour un ID donné.

par ex. Pour 123, Mike se produit le plus, le capitaine devrait être Mike. Pour 345, pas de majorité claire, donc laissez le champ du capitaine vide Pour 567, ce sera Schuyler, même si l'espace et Schuyler ont le même nombre. Pour 898 c'est Marie. Notez que Mike se produit également dans la clé 898.

Voici ma sortie.

enter image description here

Jusqu'à présent, j'ai écrit:

SELECT COUNT(*) as counts,[Class ID],Player 
    FROM [Test].[dbo].[Players] 
    GROUP BY [Class ID],Player 

qui m'a donné un résultat aussi:

enter image description here

Je suppose une procédure stockée serait la meilleure façon de écrivez ceci et obtenez la nouvelle table opposée à une nouvelle requête directe. Puisque je dois gérer le cas où s'il y a des noms identiques, le capitaine sera vide. Cependant, je suis assez nouveau pour les procédures stockées et je ne suis pas sûr de la façon de s'y prendre et de réutiliser les informations de la requête ci-dessus pour le faire et gérer les cas. Je suppose qu'il y a un CAS .. QUAND l'opération j'ai regardé dans des procédures mais je ne suis pas sûr comment je peux l'employer.

S'il vous plaît ne suggérer si vous avez une autre alternative, par opposition à la procédure. Toute aide serait appréciée.

Répondre

1

Ceci est appelé le "mode" dans les statistiques. Vous pouvez facilement faire cette fonction de fenêtre à l'aide:

SELECT [Class ID], 
     COALESCE(MAX(CASE WHEN seqnum = 1 THEN PLAYER END), MAX(CASE WHEN seqnum = 2 THEN PLAYER END) 
       ) as captain 
FROM (SELECT COUNT(*) as counts, [Class ID], Player, 
      ROW_NUMBER() OVER (PARTITION BY [Class ID] ORDER BY COUNT(*) DESC) as seqnum 
     FROM [Test].[dbo].[Players] p 
     GROUP BY [Class ID], Player 
    ) p 
GROUP BY [Class ID]; 

Note: Le COALESCE() est nécessaire parce que vous avez beaucoup de valeurs vides. Je soupçonne que vous ne les voulez pas pour le capitaine.

EDIT:

Si vous voulez pas quand il y a des liens:

SELECT [Class ID], 
     (CASE WHEN MAX(CASE WHEN seqnum = 1 AND cnt = 1 AND player IS NOT NULL THEN 1 ELSE 0 END) = 1 
      THEN PLAYER 
      WHEN MAX(CASE WHEN seqnum = 1 AND cnt > 1 THEN 1 ELSE 0 END) > 0 
      THEN NULL 
      WHEN MAX(CASE WHEN seqnum = 2 AND cnt = 1 
      THEN PLAYER 
      END) as captain 
FROM (SELECT p.*, COUNT(*) OVER (PARTITION BY [Class ID], seqnum) as cnt 
     FROM (SELECT COUNT(*) as counts, [Class ID], Player, 
        DENSE_RANK() OVER (PARTITION BY [Class ID] ORDER BY COUNT(*) DESC) as seqnum 
      FROM [Test].[dbo].[Players] p 
      GROUP BY [Class ID], Player 
      ) p 
    ) p 
GROUP BY [Class ID]; 
+0

Salut Gordon, qui est une réponse formidable. Je vous remercie. –

+0

Mais la sortie que j'obtiens est 123-> Mike, 345-> Randy, 567->, 898-> Mary 123 et 898 sont corrects. Pour 345, tous les joueurs ont des comptes égaux, donc je veux laisser le capitaine en blanc. Pour 567, Schuyler en a 2, l'espace en a 2. Les deux sont égaux mais je veux que Schuyler soit le capitaine. Comme vous pouvez voir ma sortie. Cela ressemble à SQL niveau pro! Brillant mais encore un peu loin. –

+0

SELECT [ID de la classe], COALESCE (MAX (CASE WHEN seqnum = 1 et PLAYER in ('', '') ALORS FIN FIN), MAX (CAS QUAND SEQNUM = 2 ALORS FIN JOUEUR) ) en tant que capitaine FROM (COUNT COUNT (*) as counts, [ID de classe], Player, ROW_NUMBER() OVER (PARTITION PAR [ID de classe] ORDER BY COUNT (*) DESC) comme seqnum FROM [Test]. [Dbo].[Joueurs] p GROUP BY [Classe ID], Joueur ) p GROUP BY [ID classe]; Ceci m'obtient aussi loin que la saisie d'un blanc s'il n'y a pas de comptes maximums clairs. @Gordon Linoff –