none
Impedimento al vincular una consulta dentro de otra mediante Joins RRS feed

  • Pregunta

  • Cordial saludo agradezco por favor su ayuda con el siguiente inconveniente
    tengo los siguiente para realizar la resta entre dos consultas en una misma tabla:


    SELECT * FROM
    (select DENSE_RANK() OVER(order by Oro desc , Plata desc, Bronce desc) AS idposicion,
        Pais, 
        Oro, 
        Plata, 
        Bronce, 
        Oro + Plata + Bronce AS Total 
       FROM olimpicos1)  C1 
    full outer JOIN
    (select Pais,((select Max(Oro) from olimpicos1)-Oro) as Diferencia_con_el_Maximo_de_oros from olimpicos1) C2 
    ON C1. Pais=C2. Pais ORDER BY idposicion asc,C1. Pais,C2 .Pais;

    a esto le llamo (Consulta 1)

    Al ejecutar la anterior consulta me muestra de manera adecuada lo que necesito aunque en la consulta que va despues
    del full outer JOIN Sobra el campo Pais (si quito dicho campo Pais no me muestra la consulta), pero en fin  lo importante es que me muestra lo que necesito.


    tengo otra consulta para adjuntar, pero esta no me funciona si le incluyo el campo Pais, pero si me muestra la resta que necesito, la consulta es:

      select V1.Maximo- V2.Puntaje as Resta FROM
    (
    select Max(Oro + Plata + Bronce) as Maximo FROM olimpicos1
    ) As V1, 
    (
    select(Oro + Plata + Bronce) as Puntaje FROM olimpicos1
    ) as V2;

    a esto le llamo (Consulta 2)

    El poblema de fondo es que necesito incluir esta ultima  consulta (Consulta 2) debajo de la (Consulta 1):

    SELECT * FROM
    (select DENSE_RANK() OVER(order by Oro desc , Plata desc, Bronce desc) AS idposicion,
        Pais, 
        Oro, 
        Plata, 
        Bronce, 
        Oro + Plata + Bronce AS Total 
       FROM olimpicos1)  C1 
    full outer JOIN
    (select Pais,((select Max(Oro) from olimpicos1)-Oro) as Diferencia_con_el_Maximo_de_oros from olimpicos1) C2 
    full outer JOIN
    (select V1.Maximo- V2.Puntaje as Resta FROM
    (
    select Max(Oro + Plata + Bronce) as Maximo FROM olimpicos1
    ) As V1, 
    (
    select (Oro + Plata + Bronce) as Puntaje FROM olimpicos1
    ) as V2)C3
    ON C1. Pais=C2. Pais AND C2.Pais=C3.Pais ORDER BY idposicion asc,C1. Pais,C2 .Pais,C3 .Pais;             (Linea donde muestra el error)



    Pero me muestra el siguiente error en la última linea:

    Mens. 512, Nivel 16, Estado 1, Línea 364
    La subconsulta ha devuelto más de un valor, lo que no es correcto cuando va a continuación de =, !=, <, <=, >, >= o cuando se utiliza como expresión.

    Muchas gracias por la ayuda!.

    lunes, 13 de septiembre de 2021 16:34

Todas las respuestas

  • Hola Hernan Camilo Martínez V:

    Viendo la consulta, me parece que además del error que te indica el motor, porque no puede preveer que país sea una fila única y por tanto las consultas resuelva una sola fila para un igual, se puede enfocar y quizá mejorar de otro modo.

    El escenario que planteas:

    Create table olimpicos1 (pais varchar(10), oro int, plata int, bronce int)
    GO
    iNSERT INTO olimpicos1 (pais, oro, plata, bronce)
    VALUES
    ('es',10,5 ,11),
    ('in',4 ,8 ,16),
    ('ar',6 ,9 ,9 ),
    ('br',2 ,12,2 ),
    ('zn',15,7 ,13);

    Con este ejemplo, vamos a utilizar ctes correlativas, para ir obteniendo lo que necesitamos.

    With maxOro As (
    	select top 1 Oro as maxOro from olimpicos1
    	order by oro desc
       )
       Select * from maxOro

    Con esto tenemos que el país que más oros tiene es una fila maxOro=15

    With maxOro As (
    	select top 1 Oro as maxOro from olimpicos1
    	order by oro desc
       )
       , Maximo as (
       	select Max(Oro + Plata + Bronce) as Maximo
    		FROM olimpicos1
       )
       Select * from Maximo

    Ahora tenemos una fila que nos indica cual es la cantidad máxima de medallas que tiene un pais. Una fila = 35

    With maxOro As (
    	select top 1 Oro as maxOro from olimpicos1
    	order by oro desc
       )
       , Maximo as (
       	select Max(Oro + Plata + Bronce) as Maximo
    		FROM olimpicos1
       ), data as (
    select DENSE_RANK() OVER(order by Oro desc , Plata desc, Bronce desc) AS idposicion,
        Pais, 
        Oro, 
        Plata, 
        Bronce, 
        Oro + Plata + Bronce AS Total,
    	maxOro,
    	maxOro-oro as Diferencia_con_el_Maximo_de_oros
       FROM olimpicos1
       cross join maxOro
       )
    select * from data 

    Ahora hacemos la clasificacion y cruzamos mediante un cross join los datos, con maxOro, para tener la clasificación de todos los países y la referencía del que tenga mas oros.

    Por último, cruzamos data con maximo.

    With maxOro
    	 As (Select Top 1 Oro As maxOro
    				From olimpicos1
    		 Order By oro Desc),
    	 Maximo
    	 As (Select Max(Oro + Plata + Bronce) As Maximo
    				From olimpicos1),
    	 data
    	 As (Select Dense_Rank() Over(
    				Order By Oro Desc
    					   , Plata Desc
    					   , Bronce Desc) As idposicion
    			  , Pais
    			  , Oro
    			  , Plata
    			  , Bronce
    			  , Oro + Plata + Bronce As Total
    			  , maxOro
    			  , maxOro - oro As Diferencia_con_el_Maximo_de_oros
    				From olimpicos1
    					 Cross Join maxOro)
    	 Select data.*
    		  , Maximo.Maximo
    		  , data.oro + data.plata + data.bronce As puntaje
    			From data
    				 Cross Join Maximo;

    Si observas la consulta, no dista mucho de la que has expuesto, pero el tipo de uniones, no son full outer join sino cross join, para que se reproduzca cada valor del cual tenemos 1 en cada fila del conjunto.

    Tablas de expresión correlativas

    https://javifer2.wordpress.com/2018/12/18/with-cte-tablas-de-expresion-comun-2-correlativos/

    Otra opción interesante, sería cambiar los conjuntos correlativos, por lo subconsultas correlativas con el operador apply

    Operador apply

    https://javifer2.wordpress.com/2020/06/27/operador-apply/

    Cross join

    https://www.sqlshack.com/sql-cross-join-with-examples/

    martes, 14 de septiembre de 2021 4:58