J'essaie une requête SQL (dans Oracle) pour regrouper un ensemble de données par le premier caractère de la colonne x, et obtenir également le nombre total de lignes et le nombre en pourcentage. Pour cela, j'ai utilisé le code ci-dessous.
V1 Count Percentage A 1 0.47% B 1 0.47% C 54 25.59% D 66 31.28% E 89 42.18% Total 211 99.99%
Résultat:
V1 Count Percentage A 1 0.47% B 1 0.47% C 54 25.59% D 66 31.28% E 89 42.18%
Maintenant, je veux aussi obtenir les totaux des colonnes Count et Percentage comme ci-dessous.
SELECT V1, COUNT(*) as "Count", to_char(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(), 'fm990.00')|| '%' AS "Percentage" FROM ( SELECT CASE WHEN substr(x, 0, 1) BETWEEN 'A' AND 'C' THEN 'A' WHEN substr(x, 0, 1) BETWEEN 'J' AND 'R' THEN 'B' WHEN substr(x, 0, 1) BETWEEN 'S' AND 'Z' THEN 'C' WHEN substr(x, 0, 1) BETWEEN '1' AND '5' THEN 'D' WHEN substr(x, 0, 1) BETWEEN '6' AND '7' THEN 'E' WHEN substr(x, 0, 1) BETWEEN '8' AND '9' THEN 'F' ELSE 'Unknown' END AS V1 FROM table1 ) group by V1 order by "Count", V1;
4 Réponses :
Veuillez utiliser la requête ci-dessous,
SELECT V1, COUNT(*) as "Count", to_char(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(), 'fm990.00')|| '%' AS "Percentage" FROM (SELECT CASE WHEN substr(x, 0, 1) BETWEEN 'A' AND 'C' THEN 'A' WHEN substr(x, 0, 1) BETWEEN 'J' AND 'R' THEN 'B' WHEN substr(x, 0, 1) BETWEEN 'S' AND 'Z' THEN 'C' WHEN substr(x, 0, 1) BETWEEN '1' AND '5' THEN 'D' WHEN substr(x, 0, 1) BETWEEN '6' AND '7' THEN 'E' WHEN substr(x, 0, 1) BETWEEN '8' AND '9' THEN 'F' ELSE 'Unknown' END AS V1 FROM table1 ) group by V1 order by "Count", V1 union SELECT 'Total', sum(count), sum(val)|| '%' AS "Percentage" (SELECT V1, COUNT(*) as "Count", to_char(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER(), 'fm990.00') as val; FROM (SELECT CASE WHEN substr(x, 0, 1) BETWEEN 'A' AND 'C' THEN 'A' WHEN substr(x, 0, 1) BETWEEN 'J' AND 'R' THEN 'B' WHEN substr(x, 0, 1) BETWEEN 'S' AND 'Z' THEN 'C' WHEN substr(x, 0, 1) BETWEEN '1' AND '5' THEN 'D' WHEN substr(x, 0, 1) BETWEEN '6' AND '7' THEN 'E' WHEN substr(x, 0, 1) BETWEEN '8' AND '9' THEN 'F' ELSE 'Unknown' END AS V1 FROM table1 ) group by V1 order by "Count", V1) a;
Il suffit de unir tout
votre requête avec le montant total
your query UNION ALL SELECT 'TOTAL', COUNT(*), '100%' FROM table1 GROUP BY 1;
Cela ajoute une autre ligne avec le nombre total (qui est également toujours 100%). p >
Je suggérerais de calculer le total dans la sous-requête, puis d'utiliser GROUPING SETS
:
WITH t as ( SELECT V1, COUNT(*) as "Count", TO_CHAR(COUNT(*) * 100.0 / MAX(total)|| '%' AS "Percentage" FROM (SELECT (CASE WHEN substr(x, 0, 1) BETWEEN 'A' AND 'C' THEN 'A' WHEN substr(x, 0, 1) BETWEEN 'J' AND 'R' THEN 'B' WHEN substr(x, 0, 1) BETWEEN 'S' AND 'Z' THEN 'C' WHEN substr(x, 0, 1) BETWEEN '1' AND '5' THEN 'D' WHEN substr(x, 0, 1) BETWEEN '6' AND '7' THEN 'E' WHEN substr(x, 0, 1) BETWEEN '8' AND '9' THEN 'F' ELSE 'Unknown' END) AS V1 FROM table1 ) t1 GROUP BY V1 ) SELECT v1, "Count", "Percentage" FROM t UNION ALL SELECT 'Total', SUM("Count"), TO_CHAR(TO_NUMBER(REPLACE("Percentage", '%', '')), 'fm990.00')|| '%' FROM t
MODIFIER:
En fonction de votre commentaire, vous êtes coincé avec une approche union all
:
SELECT V1, COUNT(*) as "Count", ROUND((COUNT(*) * 100.0 / MAX(total), 2) as p FROM (SELECT (CASE WHEN substr(x, 0, 1) BETWEEN 'A' AND 'C' THEN 'A' WHEN substr(x, 0, 1) BETWEEN 'J' AND 'R' THEN 'B' WHEN substr(x, 0, 1) BETWEEN 'S' AND 'Z' THEN 'C' WHEN substr(x, 0, 1) BETWEEN '1' AND '5' THEN 'D' WHEN substr(x, 0, 1) BETWEEN '6' AND '7' THEN 'E' WHEN substr(x, 0, 1) BETWEEN '8' AND '9' THEN 'F' ELSE 'Unknown' END) AS V1, COUNT(*) OVER () as total FROM table1 ) t1 GROUP BY GROUPING SETS ( (V1), () ) ORDER BY "Count", V1;
J'ai essayé cette approche plus tôt, mais le souci que j'ai est que ma colonne de pourcentage devrait totaliser 99,99% en raison d'erreurs d'arrondi dans les valeurs, mais cela renvoie 100%
@DAS. . . Intéressant. Habituellement, les gens veulent que le total représente toujours la réalité, et non les erreurs d'arrondi. Mais je peux voir l'utilité de ce que vous voulez.
Vous pouvez utiliser le ROLLUP
ici comme suit:
SELECT COALESCE(V1, 'Total'), CNT, PRCNT FROM (SELECT V1, SUM(CNT) AS CNT, SUM(PRCNT) AS PRCNT FROM (<your_existing_query>) GROUP BY ROLLUP(V1))