Ayuda (sentencias SQL): GROUP BY

Publicado en 'Programación' por eleiva, 1 Dic 2017.





  1. eleiva

    eleiva Miembro frecuente

    Registro:
    10 Abr 2017
    Mensajes:
    110
    Likes:
    21
    Temas:
    14




    Gente!, aprovechando el ambiente de mundial, solicito su apoyo para generar una consulta cuyo resultado (select aplicado a una tabla de 3 columnas) sea el país líder del grupo, grupo y puntaje. Los datos son los siguientes:

    PAIS GRUPO PUNTOS
    Rusia A 5
    Arabia Saudita A 1
    Egipto A 2
    Uruguay A 7
    Portugal B 7
    España B 3
    Marruecos B 4
    Irán B 1
    Francia C 9
    Australia C 1
    Perú C 4
    Dinamarca C 2
    Argentina D 5
    Islandia D 0
    Croacia D 7
    Nigeria D 4
    Brasil E 9
    Suiza E 6
    Costa Rica E 0
    Serbia E 3
    Alemania F 7
    México F 2
    Suecia F 3
    Corea del Sur F 2
    Bélgica G 6
    Panamá G 1
    Túnez G 1
    Inglaterra G 9
    Polonia H 3
    Senegal H 6
    Colombia H 7
    Japón H 1


    El resultado debería salir:

    pais grupo puntos
    Uruguay A 7
    Portugal B 7
    Francia C 9
    Croacia D 7
    Brasil E 9
    Alemania F 7
    Inglaterra G 9
    Colombia H 7

    Agradezco su gentil ayuda!
     


  2. ricardoegz

    ricardoegz Miembro de plata

    Registro:
    30 Dic 2012
    Mensajes:
    3,647
    Likes:
    688
    Temas:
    63
    Estoy seguro que muchos colegas del foro podrían hacer esa chambita.
    Pero en serio, asumiendo que estas dando tus pininos en el mundo de DB; no sería para nada recomendado que alguien lo hiciera por ti....
    Sugiero puedas revisar tu material y vuelvas a intentarlo.
    Esfuérzate, supérate no seas del montón.:yeah:
     
  3. ed182

    ed182 Miembro de plata

    Registro:
    5 Jun 2009
    Mensajes:
    4,554
    Likes:
    968
    Temas:
    202
  4. DarthVader

    DarthVader Miembro de oro

    Registro:
    18 Mar 2015
    Mensajes:
    8,085
    Likes:
    3,874
    Temas:
    77
  5. tenguman

    tenguman Miembro de plata

    Registro:
    15 Nov 2010
    Mensajes:
    3,437
    Likes:
    1,076
    Temas:
    68
    No entiendo q quieres q salga, solo el grupo? los cabezas de serie?
     
    A Music3000 le gustó este mensaje.
  6. ciberneuro

    ciberneuro Miembro frecuente

    Registro:
    4 Jul 2013
    Mensajes:
    170
    Likes:
    66
    Temas:
    18
    No se me ocurre como solucionar el problema con un query simple. Investiga sobre queries anidados. La pista que te doy es que deberías recorrer cada grupo en un query y obtener los datos del mejor para dicho grupo en una consulta anidada.
     
  7. DarthVader

    DarthVader Miembro de oro

    Registro:
    18 Mar 2015
    Mensajes:
    8,085
    Likes:
    3,874
    Temas:
    77
    Pero no tiene nada de complicado:

    SELECT PAÍS, GRUPO, PUNTOS FROM MYTABLE WHERE PUNTOS > 6 ORDER BY GRUPO, PUNTOS ASC;
     
    A Epikurolibre y Music3000 les gustó este mensaje.
  8. ciberneuro

    ciberneuro Miembro frecuente

    Registro:
    4 Jul 2013
    Mensajes:
    170
    Likes:
    66
    Temas:
    18
    Se puede ser el primero de un grupo con 5 puntos. También se puede ser segundo con 6 puntos. Si bien me puedes argumentar que no es el caso con la data, creo que sería importante aprender a hacer la consulta de la forma correcta y no solo para salir del pase
     
    A Music3000 le gustó este mensaje.
  9. YoProgramoEnNet

    YoProgramoEnNet Miembro nuevo

    Registro:
    3 Abr 2015
    Mensajes:
    33
    Likes:
    0
    Temas:
    4
    Como los viejos tiempos
     
  10. Epikurolibre

    Epikurolibre Miembro de plata

    Registro:
    3 Oct 2010
    Mensajes:
    3,804
    Likes:
    1,260
    Temas:
    158
    No hay mas datos para condicionar, y se atiene a lo que quiso el OP.
     
  11. tenguman

    tenguman Miembro de plata

    Registro:
    15 Nov 2010
    Mensajes:
    3,437
    Likes:
    1,076
    Temas:
    68
    A ver, yo cree una tabla en SQL con esta estructura:

    Código:
    CREATE TABLE [dbo].[Table_1](
        [idPosicion] [int] NULL,
        [Nombre_pais] [varchar](50) NOT NULL,
        [grupo] [char](1) NOT NULL,
        [puntos] [tinyint] NOT NULL
    ) ON [TABLASOTRAS]
    Inserte todos los valores mostrados por el usuario y ejecute la siguiente consulta:

    Código:
    select T1.*
    from Table_1 T1 (nolock)
    inner join (select    T.grupo as grupo,
                        MAX(T.puntos) as puntos
                from Table_1 T (nolock)
                group by T.grupo) T2
                on T2.grupo = T1.grupo and T2.puntos=T1.puntos
    order by T1.grupo
    Saliendome el siguiente resultado (solo ingrese los 4 primeros grupos)
    Código:
    idPosicion    Nombre_pais    grupo    puntos
    4    Uruguay     A    7
    5    Portugal     B    7
    9    Francia     C    9
    15    Croacia    D    7
    El asunto es que si hay dos paises con el mismo puntaje en un mismo grupo, saldrán los dos
     
  12. ciberneuro

    ciberneuro Miembro frecuente

    Registro:
    4 Jul 2013
    Mensajes:
    170
    Likes:
    66
    Temas:
    18
    Los datos son un ejemplo de lo que parece un caso de estudio. Cuando uno diseña bases de datos y queries en sistemas de información reales, uno busca cubrir todos los casos para evitar que un cambio en la base de datos (permitido por el sistema) malogre nuestros reportes. Creo que es mejor aprender de esa forma a buscar una forma simplificada que sólo funciona para un caso.

    En MySQL, una forma de solucionar el problema sería:
    Código:
    select distinct e.grupo, e.pais, e.puntos
    from equipos e
    where (select e2.pais
       from equipos e2
       where e2.grupo=e.grupo
       order by puntos desc
       limit 1
       ) = e.pais
    http://sqlfiddle.com/#!9/7b595d/9
     
  13. gnox

    gnox Miembro de bronce

    Registro:
    3 Ene 2013
    Mensajes:
    1,508
    Likes:
    564
    Temas:
    56
    Código:
    select e.grupo, e.pais, e.puntos
    from equipos e
    where e.puntos = (select max(e2.puntos)
       from equipos e2
       where e2.grupo=e.grupo
    )
    
     
  14. ciberneuro

    ciberneuro Miembro frecuente

    Registro:
    4 Jul 2013
    Mensajes:
    170
    Likes:
    66
    Temas:
    18
    Buena opción. Tener en cuenta que, en caso de empates, tu query devolvería 2 registros por el grupo.
    Debido a que no hay mayor detalles ni información sobre empates (diferencia de goles u otro criterio), creo que este detalle es desestimable en este caso.
     
  15. eleiva

    eleiva Miembro frecuente

    Registro:
    10 Abr 2017
    Mensajes:
    110
    Likes:
    21
    Temas:
    14
    Exacto; puede darse el caso de que 3 equipos del mismo grupo estén con 5 puntos (como el grupo de México en USA 94), y también 3 equipos del mismo grupo pueden estar con 6 puntos cada uno (como el grupo de Argentina en USA 94). Eso de ponerle ">6" fue lo primero que hice pero no es la solución que busco.

    Gracias man... déjame probar esa solución. No importa que 2 países tengan igualdad de puntos... puse esos ejemplos sin tener en cuenta esa casuistica, puesto que no me interesa de momento (en todo caso, agrego una columna "diferencia de goles" y ya podría sacarlo).

    El caso que puse es base para otro que (también quiero sacar)... lo explicaré en unos minutos en otro post).

    Estimados, vuelvo a molestarlos con una pregunta más del mismo caso... ahora el tema es el siguiente: quisiera elaborar un query en donde me salgan LOS SEGUNDOS de cada grupo:

    PAIS GRUPO PUNTOS
    Rusia A 5
    Arabia Saudita A 1
    Egipto A 2
    Uruguay A 7
    Portugal B 7
    España B 3
    Marruecos B 4
    Irán B 1
    Francia C 9
    Australia C 1
    Perú C 4
    Dinamarca C 2
    Argentina D 5
    Islandia D 0
    Croacia D 7
    Nigeria D 4
    Brasil E 9
    Suiza E 6
    Costa Rica E 0
    Serbia E 3
    Alemania F 7
    México F 2
    Suecia F 3
    Corea del Sur F 2
    Bélgica G 6
    Panamá G 1
    Túnez G 1
    Inglaterra G 9
    Polonia H 3
    Senegal H 6
    Colombia H 7
    Japón H 1


    El resultado debería salir:

    pais grupo puntos
    Rusia A 5
    Marruecos B 4
    Perú C 4
    Argentina D 5
    Suiza E 6
    Suecia F 3
    Bélgica G 6
    Senegal H 6

    Agradezco nuevamente su gentil ayuda!
     
  16. tenguman

    tenguman Miembro de plata

    Registro:
    15 Nov 2010
    Mensajes:
    3,437
    Likes:
    1,076
    Temas:
    68
    para eso, reutilizando la tabla:
    Código:
    CREATE TABLE [dbo].[Table_1](
        [idPosicion] [int] NULL,
        [Nombre_pais] [varchar](50) NOT NULL,
        [grupo] [char](1) NOT NULL,
        [puntos] [tinyint] NOT NULL
    ) ON [TABLASOTRAS]
    insertando los registros de los 4 primeros grupos:
    Código:
    insert into [Table_1] VALUES (1, 'Rusia','A',5)
    insert into [Table_1] VALUES (2, 'Arabia Saudita','A',1)
    insert into [Table_1] VALUES (3, 'Egipto','A',2)
    insert into [Table_1] VALUES (4, 'Uruguay','A',7)
    insert into [Table_1] VALUES (5, 'Portugal','B',7)
    insert into [Table_1] VALUES (6, 'España','B',3)
    insert into [Table_1] VALUES (7, 'Marruecos','B',4)
    insert into [Table_1] VALUES (8, 'Irán','B',1)
    insert into [Table_1] VALUES (9, 'Francia','C',9)
    insert into [Table_1] VALUES (10, 'Australia ','C',1)
    insert into [Table_1] VALUES (11, 'Perú ','C',4)
    insert into [Table_1] VALUES (12, 'Dinamarca ','C',2)
    insert into [Table_1] VALUES (13, 'Argentina ','D',5)
    insert into [Table_1] VALUES (14, 'Islandia ','D',0)
    insert into [Table_1] VALUES (15, 'Croacia ','D',7)
    insert into [Table_1] VALUES (16, 'Nigeria ','D',4)
    
    pirañeo el codigo que puso @ciberneuro que creo que es el mas eficaz y lo modifico para q devuelva el segundo en SQL Server

    (basicamente primero devuelvo los dos primeros de cada grupo y luego le resto el primero con EXCEPT)
    Código:
    select distinct e.grupo, e.Nombre_pais, e.puntos
    from Table_1 e
    where ( select top 2 e2.Nombre_pais
            from Table_1 e2
            where e2.grupo=e.grupo
            order by puntos desc
            EXCEPT
            select top 1 e2.Nombre_pais
            from Table_1 e2
            where e2.grupo=e.grupo
            order by puntos desc
        ) = e.Nombre_pais
    Retorna los siguientes valores
    Código:
    grupo    Nombre_pais    puntos
    A        Rusia            5
    B        Marruecos        4
    C        Perú             4
    D        Argentina        5
     
    Última edición: 6 Dic 2017
  17. gnox

    gnox Miembro de bronce

    Registro:
    3 Ene 2013
    Mensajes:
    1,508
    Likes:
    564
    Temas:
    56
    Código:
    select e.grupo, e.pais, e.puntos
    from equipos e
    where e.puntos = (select max(e2.puntos)
       from equipos e2
       where e2.grupo=e.grupo and
       e2.puntos <
       (select max(e3.puntos) from
        equipos e3 where e3.grupo = e2.grupo)
    )
    
     
Etiquetas: