SQL - Consulta por quintiles

   
Vista:

Consulta por quintiles

Publicado por Jhonatan (2 intervenciones) el 26/04/2016 01:37:45
Hola, por favor necesito hacer una consulta en sql separada por quintiles, según el rankign del Campo total

ejemplo:

Quintil Total Referencia

Quintil_1 100 A
Quintil_1 102 B
Quintil_1 103 C
Quintil_1 99 D
Quintil_1 89 E
Quintil_2 70 F
Quintil_2 60 G
Quintil_2 54 H
Quintil_2 59 I
Quintil_2 10 J
Quintil_3 08 K


Gracias por su apoyo
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Consulta por quintiles

Publicado por leonardo_josue (877 intervenciones) el 26/04/2016 19:15:49
Hola Jhonathan:

No me quedó muy claro qué es lo que pretendes así es que comencemos desde un inicio...

1. ¿A qué re refieres con QUINTILES?... por definición, un quintil es la quinta parte de algo, (en estadística es la quinta parte de la muestra ordenada de mayor a menor, de tal suerte que si tu muestra es por ejemplo de 10 elemento entonces un quintil tendría un tamaño de 2 elementos...

En tu caso en realidad lo que haces es separar de cinco en cinco, por lo tanto estamos hablando de cosas muy distintas.

2. según tu definición estás ordenando según el rankign del Campo total, sin embargo, en el ejemplo veo que NO ESTÁS COLOCANDO UN ORDEN:

1
2
3
4
5
Quintil_1	100	A
Quintil_1	102	B
Quintil_1	103	C
Quintil_1	99	D
Quintil_1	89	E

si ordenaras por TOTAL entonces los registros deberían quedar así:

1
2
3
4
5
Quintil_1	103
Quintil_1	102
Quintil_1	100
Quintil_1	99
Quintil_1	89

y lo mismo pasa con el resto de los registros.

3. ¿Con qué BD's estás trabajando? aunque la mayoría de los motores tienen una sintaxis parecida, hay diferencias importantes entre cada uno de ellos, por lo tanto la respuesta puede variar bastante para cada caso.

4. ¿Qué haz intentado hacer? porque puedo suponer que al menos trataste de hacer algo. Postea siempre algo del código que intentaste y dinos qué está mal, así como lo expones tal pareciera que estás esperando a que alguien haga tu trabajo.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Consulta por quintiles

Publicado por Jhonatan (2 intervenciones) el 26/04/2016 23:04:17
Hola Leo, gracias por el aporte.
Según tu punto 1 es exactamente lo que deseo hacer. Solo que me explique de manera confusa y puso un ejemplo la más simple que puede pensarlo, ya que mi código tiene entre otras cosas que pueden confundir aún mas.

ojala que con esto despeje tus dudas:

1
2
3
4
5
6
7
8
9
Select Dense_Rank() Over(Order By A.Cod_Mes, A.Producto, A.Cargo_Final, A.[%_Cump] Desc) As 'Rank', B.Conteo, B.Conteo/5 Quinto, A.Cod_Mes, A.Producto, A.Cargo_Final, A.[%_Cump], A.*
From DataA,
(
	Select Ltrim(Rtrim(IsNull(Cod_Mes,0)))+Ltrim(Rtrim(IsNull(Cargo_Final,0)))+Ltrim(Rtrim(IsNull(Producto,0)))Llave,
	Cod_Mes, Cargo_Final, Producto, Count(*)Conteo
	From DataA
	Group By Cod_Mes, Cargo_Final, Producto
)B
Where Ltrim(Rtrim(IsNull(A.Cod_Mes,0)))+Ltrim(Rtrim(IsNull(A.Cargo_Final,0)))+Ltrim(Rtrim(IsNull(A.Producto,0)))=B.Llave

Te explico en el query lo que hago:
1.- Cuento cuantos registros hay que cumplen una determinada condición.
2.- El resultado lo divido entre 5 para saber la cantidad de registros en cada quintil.
3.- hallo el campo Ranking para ranquear los datos de mayor a menor que cumplan con las condiciones del punto uno.

ahora con este resultado quiero separar la consulta con un campo adicional "quintil"

Quintil_1, Quintil_2, Quintil_3... hasta que se termine hasta que se termine el primer grupo (del campo "conteo")

intente con la función ROW_NUMBER pero no he podido hallar la solución y postee el caso por este medio.

Saludos.
Jhonatan
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Consulta por quintiles

Publicado por leonardo_josue (877 intervenciones) el 27/04/2016 18:34:21
Hola de nuevo Jhonatan:

Alguna vez uno de mis maestros me dijo que hay muchas maneras de matar una mosca, pero utilizar una pistola puede ser demaciado. Creo que esto aplica en lo que estás tratando de hacer, la solución puede atacarse de manera más simple...

No nos mencionas con qué BD's estás trabajando, pero creo que este ejemplo te puede servir. De entrada te comento que es muy probable que tengas que hacer un SP o procedimiento almacenado para lograr lo que quieres... igual y puedes hacerlo con una consulta SQL, pero no será nada simple. No nos dices con qué BD's estás trabajando, pero voy a poner un ejemplo en MySQL que te puede servir:

En matemáticas existe una operación para obtener la parte entera de una división, es decir, algo como esto:

1
2
3
4
5
6
7
8
9
0 div 3 = 0
1 div 3 = 0
2 div 3 = 0
3 div 3 = 1
4 div 3 = 2
....
13 div 3 = 4
14 div 3 = 4
15 div 3 = 5

Por lo tanto, puedes utilizar esta técnica para obtener lo que quieres. Supongamos que tienes estos datos en tu tabla:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> SELECT total FROM tabla ORDER BY total DESC;
+-------+
| total |
+-------+
|   110 |
|   107 |
|   100 |
|    99 |
|    98 |
|    96 |
|    90 |
|    83 |
|    80 |
|    79 |
|    75 |
|    70 |
|    61 |
|    50 |
|    35 |
+-------+
15 rows in set (0.00 sec)

Tal como dices, para obtener el tamaño del cuantil calculas el total de registros y lo divides entre 5 (en este caso sería 3):

1
2
3
4
5
6
7
8
9
10
mysql> SET @tam_quintil = (SELECT COUNT(total) FROM tabla) / 5;
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT @tam_quintil;
+--------------+
| @tam_quintil |
+--------------+
|  3           |
+--------------+
1 row in set (0.00 sec)

El siguiente paso es numerar los registros para asignarles un consecutivo, de tal suerte que tengas algo como esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
mysql> SET @i=-1;
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT
    -> @i:=@i+1,
    -> total
    -> FROM tabla ORDER BY total DESC;
+----------+-------+
| @i:=@i+1 | total |
+----------+-------+
|        0 |   110 |
|        1 |   107 |
|        2 |   100 |
|        3 |    99 |
|        4 |    98 |
|        5 |    96 |
|        6 |    90 |
|        7 |    83 |
|        8 |    80 |
|        9 |    79 |
|       10 |    75 |
|       11 |    70 |
|       12 |    61 |
|       13 |    50 |
|       14 |    35 |
+----------+-------+
15 rows in set (0.00 sec)

En tu caso, puedo suponer por la sintaxis que manejas que estás trabajando con SQL Server o con ORACLE, ahí hay funciones para generar consecutivos con las mismas funciones rank o row_number.

Una vez teniendo esto, entonces simplemente aplicas una DIVISION ENTERA del consecutivo entre el numero que resultó del quintil,
en otras palabras harías algo como esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
mysql> SET @tam_quintil = (SELECT COUNT(total) FROM tabla) / 5;
Query OK, 0 rows affected (0.00 sec)
 
mysql> SET @i=-1;
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT CONCAT('Quintil_', (consecutivo DIV @tam_quintil) + 1) quintil, total FROM
    -> (
    ->    SELECT
    ->      @i:=@i+1 consecutivo,
    ->      total
    ->    FROM tabla
    ->    ORDER BY total DESC ) T;
+-----------+-------+
| quintil   | total |
+-----------+-------+
| Quintil_1 |   110 |
| Quintil_1 |   107 |
| Quintil_1 |   100 |
| Quintil_2 |    99 |
| Quintil_2 |    98 |
| Quintil_2 |    96 |
| Quintil_3 |    90 |
| Quintil_3 |    83 |
| Quintil_3 |    80 |
| Quintil_4 |    79 |
| Quintil_4 |    75 |
| Quintil_4 |    70 |
| Quintil_5 |    61 |
| Quintil_5 |    50 |
| Quintil_5 |    35 |
+-----------+-------+
15 rows in set (0.00 sec)

Que desde mi punto de vista es lo que necesitas. Checa el ejemplo y trata de aplicarlo en el motor de BD's que estés utilizando, si continuas con problemas lo comentas y revisamos tu código.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar