Tengo una tabla SQL con una columna de elementos que quiero mostrar el porcentaje de los recuentos totales de cada elemento en orden desc.

Por ejemplo,

Column A
Item 1
Item 1
Item 2
Item 3

Me gustaría mostrar:

Column A
Item 1   0.5
Item 2   0.25
Item 3   0.25

Hasta ahora he intentado lo siguiente:

SELECT [Column A], (count([Column A]) / count(*))
  FROM [table]
  GROUP BY [Column A]
  Order by (count([Column A]) / count(*)) DESC

Sin embargo, todo vuelve como 1.

2
notlaughing 9 sep. 2018 a las 02:12

3 respuestas

La mejor respuesta

Puede intentar agrupar COUNT por [Column A] columna en la consulta principal. luego haga un total count en la subconsulta do division.

CREATE TABLE T(
   [Column A] VARCHAR(50)
); 

INSERT INTO T VALUES ('Item 1');
INSERT INTO T VALUES ('Item 1');
INSERT INTO T VALUES ('Item 2');
INSERT INTO T VALUES ('Item 3');

SELECT [Column A],COUNT(*) /CAST ((SELECT COUNT(*) FROM T) AS FLOAT)
FROM T 
GROUP BY [Column A]

sqlfiddle

O puede usar CROSS JOIN para obtener el total y luego hacer la división.

SELECT [Column A],COUNT(*) /CAST(total AS FLOAT)
FROM T CROSS JOIN (SELECT COUNT(*) total FROM T) v
GROUP BY [Column A],total
1
D-Shih 8 sep. 2018 a las 23:17

Creo que las funciones de Windows son una mejor solución para este tipo de casos porque la tabla se lee una vez.

¿Si en lugar de un porcentaje único tiene que crear un porcentaje, un promedio y una suma? ¿O la consulta es más compleja que un solo recuento? Crear muchas subconsultas no es una opción. Entonces, esta es la razón por la que prefiero las funciones de ventana en lugar de las subconsultas.

dbfiddle

CREATE TABLE T(
   [Column A] VARCHAR(50)
); 

INSERT INTO T VALUES ('Item 1');
INSERT INTO T VALUES ('Item 1');
INSERT INTO T VALUES ('Item 2');
INSERT INTO T VALUES ('Item 3');

SELECT
   [Column A], CNT / SUM(CNT) OVER () PERC
FROM (
  SELECT [Column A], CAST(COUNT(*) AS NUMERIC) CNT
  FROM T 
  GROUP BY [Column A]
) X
ORDER BY PERC
0
lmarqs 9 sep. 2018 a las 00:15

Su problema es que su agregado se aplica en la columna agrupada, independientemente, necesitará obtener el total por separado de alguna manera. Una forma sería usar una tabla derivada como con @ D-Shih. Solo lo voy a almacenar en una variable.

El otro problema que tiene es que sus dos operandos son INT, por lo que SQL Server está infiriendo el tipo de datos de INT para el resultado. solo necesita uno de los operandos para no devolver un tipo de datos entero. He usado un tipo de datos numérico exacto porque los números numéricos aproximados podrían causar problemas si luego necesita sumar el% individual para obtener el 100%.

DECLARE @t_item TABLE
(       name VARCHAR(10)
)

DECLARE @total_count NUMERIC(3,2)

INSERT INTO @t_item
VALUES ('ITEM1'),
       ('ITEM1'),
       ('ITEM2'),
       ('ITEM3'),
       ('ITEM3'),
       ('ITEM1')

SELECT @total_count = COUNT(*) FROM @t_item

SELECT name,
       COUNT(name),
       COUNT(*),
       pct_of_all      = CONVERT(NUMERIC(3,2),COUNT(name))/CONVERT(NUMERIC(3,2),COUNT(*))
  FROM @t_item
 GROUP BY name


SELECT name,
       COUNT(name),
       @total_count,
       pct_of_all      = COUNT(name)/@total_count
  FROM @t_item
 GROUP BY name
0
G B 8 sep. 2018 a las 23:50