2010-12-11 4 views
4

je tente de le faire:Méthode la plus simple pour obtenir le nombre total et le nombre de sous-ensembles?

SELECT COUNT(*), 
     (
      SELECT COUNT(*) FROM attend 
      WHERE (DATEPART(WEEKDAY,start_date) = 2 OR DATEPART(WEEKDAY,start_date) = 6) 
      AND empl_no = 12345 
     ) 
     FROM attend as a 
WHERE empl_no = 12345 

Mais cela semble un peu laid. Y a-t-il une meilleure manière de faire cela?

+0

Est-ce le double où l'utilisation des pièces de clause ou répétées de même table que vous trouvez laid? – JeffO

+0

Plus la sous-requête. –

+1

FYI: Un CTE n'offre aucun avantage de performance - la réponse de nate c est le moyen le plus efficace. –

Répondre

6

Vous pouvez utiliser un CTE:

WITH T1 AS (
    SELECT DATEPART(WEEKDAY,start_date) AS weekday 
    FROM attend 
    WHERE empl_no = 12345 
) 
SELECT 
    (SELECT COUNT(*) FROM T1) AS total, 
    (SELECT COUNT(*) FROM T1 WHERE weekday = 2 OR weekday = 6) AS subset 
+0

Y a-t-il une différence de performance entre nos solutions? –

+1

Ne pas cliquer deux fois sur la table d'attente devrait vous aider à améliorer les performances, surtout si votre requête concerne d'autres tables. – JeffO

+0

@abe Miessler: Si vous êtes préoccupé par les performances, alors la toute première chose à faire est que vous avez correctement indexé votre table, sinon toutes les solutions fonctionneront mal. Vous avez probablement besoin d'un index sur 'empl_no'. –

0

CUBE et ROLLUP sont très utiles pour traiter les agrégats finaux et intermédiaires tout en un seul coup. Pour ce type de question, CUBE serait un bon ajustement si les totaux final et intermédiaire étaient nécessaires afin que cette question et des questions similaires puissent être répondues sans requêtes supplémentaires de la table source. J'ai trouvé CUBE très utile pour éviter les allers-retours à la DB. Cependant, dans le cas où les exigences exactes sont connues à l'avance, un seul choix ciblé (bien démontré par @nate c) est le plus logique.

DECLARE @T1 TABLE (total int, weekday int) 

INSERT INTO @T1 
SELECT COUNT(1), DATEPART(WEEKDAY,start_date) 
FROM attend 
WHERE empl_no = 12345 
GROUP BY DATEPART(WEEKDAY,start_date) WITH CUBE 

SELECT 
    (SELECT Total FROM @T1 WHERE weekday is NULL) AS total, 
    (SELECT SUM(weekday) FROM @T1 WHERE weekday = 2 or weekday = 6) AS subset 

-- continue using @T1 or a table variable was seriously overkill 
+0

Ne faites jamais dans deux requêtes, ce que vous pouvez faire en un. En outre, le CTE n'offre aucune amélioration des performances - le contenu CTE est réexécuté pour chaque sous-sélection. –

+0

@OMG Poneys: bon appel. J'ai enlevé la mention de CTE et reformulé l'utilité de CUBE pour ceci. –

9

Utilisation:

SELECT COUNT(*) AS total, 
     SUM(CASE 
      WHEN DATEPART(WEEKDAY, t.start_date) IN (2,6) THEN 1 
      ELSE 0 
      END) AS weekday 
    FROM ATTEND t 
WHERE t.empl_no = 12345 
Questions connexes