none
Problemas con una SQL RRS feed

  • Pregunta

  • Buenos días, tengo problemas con una sentencia SQL, intentamos construirla, para que funcion correctamente en SQL Server y en Oracle. La SQL Original es:

                                                     

    SELECT   
    tcVeh.NumStock as tcVeh_numstock, 
    tcVeh.Numpedido as tcveh_Numpedido,  
    tcVeh.NumPedidoFab as NumPedidoFab,   
    tcVeh.NumLlaves as tcVeh_NumLlaves,   
    tcVeh.CodigoRadio as tcVeh_CodigoRadio,  
    tcVeh.NumMotor as tcVeh_NumMotor,   
    tcVeh.NumCaja as tcVeh_NumCaja,   
    tcVeh.Status as tcveh_status,
    tcVeh.SubStatus as tcveh_substatus,      
    tcVeh.HayFactur as tcveh_hayfactur,
    tcVeh.EsKm0 AS tcVeh_EsKm0,   
    tcVeh.EsDemo AS tcVeh_EsDemo, 
    tcVeh.EsCortesia AS tcVeh_EsCortesia,   
    tcveh.esServicio AS tcveh_esServicio,
    tcveh.FecMatricPrimera as tcveh_FecMatricPrimera, 
    tcPresupuesto.FechaFactura as FechaFactura,     
    tcPresupuesto.Flota as tcPresupuesto_Flota,
    tcPresupuesto.Expediente as tcPresupuesto_Expediente,  
    tcPresupuesto.vendedor as tcPresupuesto_vendedor,
    tcComisReclam.Descrip as tcComisReclam_Descrip,   
    tgProveedor.Apellido1 as tgProveedor_Apellido1,   
    tgProveedor.Apellido2 as tgProveedor_Apellido2,   
    tgProveedor.Nombre as tgProveedor_Nombre,   
    tgProveedor.PerJuridica as tgProveedor_PerJuridica,   
    tgModelo.Descrip as tgModelo_Descrip,   
    tgMarca.Descrip as tgMarca_Descrip,   
    tgVersion.Descrip as tgVersion_Descrip,   
    tgPtoVenta.Descrip as tgPtoVenta_Descrip,   
    tgCategoria.Descrip as tgCategoria_Descrip,   
    tcTapiz.Descrip as tcTapiz_Descrip,
    tcPresupuesto.Emp AS tcPresupuesto_Emp,   
    tcColor.Descrip as tcColor_Descrip,
    case  
    when (tcveh.esvo = 0 and tcPresupuesto.Numinterno > 0) then (SELECT tgClienteFac.CialAgrupCliente from tgclienteFac where tgclientefac.emp = tcpresupuesto.emp 
    and tgclientefac.Codigo = tcpresupuesto.clientefac)
    else ''
    end as CialAgrupcliente,
    case  
    when  (tcveh.esvo = 1 and tcPresupuesto.Numinterno > 0) then (SELECT tgClienteFac.VOAgrupCliente   from tgclienteFac where tgclientefac.emp = tcpresupuesto.emp and tgclientefac.Codigo = tcpresupuesto.clientefac)
    else ''
    end as VOAgrupCliente,
    dbo.fn_ICarDMS_razon_Codigo(tgProveedor.Codigo,1) AS tgProveedor_cmp_razon,
    (SELECT coalesce(tgAgrupCliente.Descrip,'')

    FROM tgAgrupCliente
    WHERE tgAgrupCliente.Codigo in (SELECT tgClienteFac.CialAgrupCliente from tgclienteFac where tgclientefac.emp = tcpresupuesto.emp 
    and tgclientefac.Codigo = tcpresupuesto.clientefac) AND
    tgAgrupCliente.EsCial = 1
    )as cialagrupcliente_comp,
    dbo.fn_ICarDMS_GetYear (tcpresupuesto.FechaFactura)  as anoFechaFactura_comp,
    dbo.fn_ICarDMS_razon_Codigosc(tcpresupuesto.clientefac,0) as clientefacrazon_comp,
    dbo.fn_ICarDMS_razon_Codigosc(tcpresupuesto.clienteprop,0) as clienteproprazon_comp,
    dbo.fn_ICarDMS_razon_Codigosc(tcpresupuesto.clientecond,0) as clientecondrazon_comp,
    coalesce(tcvehsubstatus.descrip,'') as substatus_descrip,
    dbo.fn_ICarDMS_GetMonth(tcpresupuesto.FechaFactura) as mesFechaFactura_comp,
    coalesce(tcubicacion.descrip,'') as tcubicacion_descrip,
    dbo.fn_ICarDMS_razon_vendedor(tcPresupuesto.vendedor,tcPresupuesto.Emp) 
    as vendedorrazon,
    (select Coalesce(tgAgrupCliente.Descrip,'') from tgAgrupCliente
    where tgAgrupCliente.Codigo in (SELECT tgClienteFac.voagrupcliente 
                                         from tgclienteFac where tgclientefac.emp = tcpresupuesto.emp and
                                         tgclientefac.Codigo = tcpresupuesto.clientefac)
    and  tgAgrupCliente.EsCial   = 1)
    as voagrupcliente_comp,
    tcveh.vehiculomaestro as tcveh_vehiculomaestro,
    tcveh.expediente as tcVeh_Expediente,
    tcPresupuesto.ClienteFac as tcPresupuesto_ClienteFac,
    tcPresupuesto.ClienteProp as tcPresupuesto_ClienteProp,
    tcPresupuesto.ClienteCond as tcPresupuesto_ClienteCond,
    tcPresupuesto.NumInterno as tcPresupuesto_NumInterno,
    tcveh.numfacturaprovee as numfacturaprovee,
    tgcliente.apellidosearch as apellidosearch,
    tcPresupuesto.vehiculo as tcPresupuesto_vehiculo,
    dbo.fn_ICarDMS_CodigoFabri(tcVeh.Marca,tcPresupuestoComisReclam.Campana) as codigofabri_comp,
    tcPresupuestoComisReclam.Abonada As Abonada,
    tcPresupuestoComisReclam.UsuarioContab As UsuarioContab,
    tcPresupuestoComisReclam.TipoFacturacion As TipoFacturacion,
    tcPresupuestoComisReclam.AnoFactura As AnoFactura,
    tcPresupuestoComisReclam.NumFactura As NumFactura,
    tcPresupuestoComisReclam.ContadorFac As ContadorFac,
    tcPresupuestoComisReclam.CosteContab As CosteContab,
    tcPresupuestoComisReclam.AgrupCliente As AgrupCliente,
    tcPresupuestoComisReclam.CosteVenta As CosteVenta,
    tcPresupuestoComisReclam.EmpCobro As EmpCobro,
    (select tcvehfactur.fechafactura 
    From tcvehfactur 
    Where tcvehfactur.Emp =tcveh.Emp 
    and tcvehfactur.NumInterno = tcveh.NumInterno
    and tcvehfactur.tipofactura = 'VE'
    and tcvehfactur.linea = (select MIN(linea) 
    from tcvehfactur    tcvf         
    where tcvf.emp = tcveh.emp
    and tcvf.numinterno = tcveh.numinterno
    and tcvf.tipofactura = 'VE')) AS FechaPrimeraFactura,
    tcPresupuesto.NumFactura As tcPresupuesto_NumFactura,
    Case 
    when tmPSAInterface.gestionopv = 1 then
    tmPSAOPVCliPedido.DateVenteDetailVN
    else
    (SELECT MAX(PVVDG1.DateVteDet)
    FROM tmPEUVehVteDetGeneral PVVDG1
    WHERE PVVDG1.VehEmp = tcVeh.Emp
    AND PVVDG1.VehNumInterno = tcVeh.NumInterno
    AND PVVDG1.CodeMouvement = '2320'
    AND PVVDG1.DateMouvement = (SELECT MAX(PVVDG2.DateMouvement)
    FROM tmPEUVehVteDetGeneral PVVDG2
    WHERE PVVDG2.CodeMouvement = '2320'
    AND PVVDG2.Tratado = 1
    AND PVVDG2.VehEmp = PVVDG1.VehEmp
    AND PVVDG2.VehNumInterno = PVVDG1.VehNumInterno ))
    end AS DateVenteDetailVN

    FROM 
    tcPresupuestoComisreclam LEFT OUTER JOIN tcPresupuesto ON tcPresupuestoComisreclam.Emp = tcPresupuesto.Emp AND  
    tcPresupuestoComisreclam.NumInterno = tcPresupuesto.NumInterno
    LEFT OUTER JOIN tgProveedor ON tcPresupuestoComisreclam.Proveedor  = tgProveedor.Codigo,    
    tcVeh LEFT OUTER JOIN tgPtoVenta ON tcVeh.Emp = tgPtoVenta.Emp AND 
    tcVeh.PuntoVenta = tgPtoVenta.PuntoVenta
    LEFT OUTER JOIN tcColor ON tcVeh.Marca = tcColor.Marca AND 
    tcVeh.Color = tcColor.Color 
    LEFT OUTER JOIN tcTapiz ON tcVeh.Marca = tcTapiz.Marca AND 
    tcVeh.Tapiz = tcTapiz.Tapiz 
    LEFT OUTER JOIN tgCategoria ON tcVeh.Categoria = tgCategoria.Categoria
    LEFT OUTER JOIN tcvehsubstatus   ON tcveh.status=tcvehsubstatus.status AND 
    tcveh.substatus=tcvehsubstatus.substatus
    LEFT OUTER JOIN tcUbicacion ON tcveh.ubicacion=tcUbicacion.ubicacion AND
    tcveh.emp= tcUbicacion.emp
    LEFT OUTER JOIN tgcliente on tgcliente.codigo = tcveh.reservacliente
    LEFT OUTER JOIN tmPSAInterface ON tmPSAInterface.Item = 1
    LEFT JOIN tmPSAOPVCliPedido
    ON tcVeh.NumPedidoFab = tmPSAOPVCliPedido.CAR
    AND tmPSAOPVCliPedido.IdCliPedido = (SELECT MAX(tmPSAOPVCliPedido.IdCliPedido)
    FROM tmPSAOPVCliPedido
    WHERE tmPSAOPVCliPedido.CAR = tcVeh.NumPedidoFab),
    tcComisReclam,   
    tgMarca,   
    tgModelo,   
    tgVersion

    WHERE 
    ( tcPresupuestoComisreclam.Emp = tcComisReclam.Emp ) and  
    ( tcPresupuestoComisreclam.Comision = tcComisReclam.Comision ) and  
    ( tcPresupuestoComisreclam.Emp = tcVeh.Emp ) and  
    ( tcPresupuestoComisreclam.NumInternoVeh = tcVeh.NumInterno ) and  
    ( tcVeh.Marca = tgMarca.Marca ) and  
    ( tcVeh.Modelo = tgModelo.Modelo ) and  
    ( tcVeh.Marca = tgModelo.Marca ) and  
    ( tcVeh.Marca = tgVersion.Marca ) and  
    ( tcVeh.Modelo = tgVersion.Modelo ) and  
    ( tcVeh.Version = tgVersion.Version ) and
    ( tcVeh.Status <> -1 ) and    
    (tcPresupuestoComisreclam.Emp = :as_emp ) AND  
    (tcVeh.EsVO = :al_Esvo )  

    El problema es docle, el últom LEFT JOIN tal y como está SQL Server si lo acepta pero ORACLE no, asi es que lo he cambiado por el siguiente:

    LEFT JOIN (SELECT *
    FROM tmPSAOPVCliPedido
    WHERE tmPSAOPVCliPedido.IdCliPedido = (SELECT MAX(psa2.IdCliPedido)
    FROM tmPSAOPVCliPedido psa2
    WHERE psa2.CAR = tcVeh.NumPedidoFab)) tmPSAOPVCliPedido
    ON tcVeh.NumPedidoFab = tmPSAOPVCliPedido.CAR,

    El problema es que si hacemos esto, tanto ORACLE como SQL Server me dan un error con código 4104 y Descripción de Error "El identificador formado por varias partes 'tcveh.NumPedidoFab' no se pudo enlazar.

    Pueden ayudarme....

    jueves, 6 de septiembre de 2018 7:04

Respuestas

  • Hola Juan Manuel Pardo García:

    Vaya por delante desde mi opinión, que tu consulta para analizar y en dos motores diferentes, parece un "locurón".

    Pero porque no haces el LEFT JOIN contra la tabla, y luego el max, lo limitas en el where, ya que Oracle no te permite relacionarlo contra esa subconsulta.

    Por otro lado en la segunda parte que expones, el select * no vale, tienes que darle un alias a la tabla derivada

    LEFT JOIN (SELECT * FROM ……..) AS O  ON O.CAMPO =

    Un saludo

    jueves, 6 de septiembre de 2018 7:26
  • Estas mezclando el viejo y nuevo estilos de unir tablas:

    Viejo: select * from T1, T2 where ...

    Nuevo: select * from T1 inner join T2 on ...

    Aca la parte de tu query haciendo la mezcla:

        LEFT OUTER JOIN
        tgProveedor
        ON tcPresupuestoComisReclam.Proveedor = tgProveedor.Codigo
    	
        ,tcVeh
    
        LEFT OUTER JOIN
        tgPtoVenta
        ON tcVeh.Emp = tgPtoVenta.Emp
        AND  tcVeh.PuntoVenta = tgPtoVenta.PuntoVenta
    
    ...
    
        LEFT JOIN
        tmPSAOPVCliPedido
        ON tcVeh.NumPedidoFab = tmPSAOPVCliPedido.CAR
        AND  tmPSAOPVCliPedido.IdCliPedido = (
               SELECT
                    MAX(tmPSAOPVCliPedido.IdCliPedido)
               FROM
                    tmPSAOPVCliPedido
               WHERE
                    tmPSAOPVCliPedido.CAR = tcVeh.NumPedidoFab
        )
    	
    	,
        tcComisReclam,
        tgMarca,
        tgModelo,
        tgVersion
    
    WHERE
    ...

    Es importante que pongas atencion a esto, pues cuando usamos LEFT OUTER JOIN estamos diciendole a SQL Server que la tabla a preservar es la del lado izquierdo y que las columnas referenciadas del lado derecho que no machen una fila del lado izquierdo se usara la marca NULL.  Luego tu en la clausula WHERE referencias esas columnas pero como NULL no se puede comparar usando operadores como =, >, =>, etc. entonces estarias desechando esas filas.  La forma correcta es poniendo esas restricciones comoparte de la union.

    Ejemplo:

    select *
    from T1 left outer join T2 on T2.id = T1.id
    where T2.col2 < 10  -- <<<<< incorrecto

    select *
    from T1 left outer join T2 on T2.id = T1.id and T2.col2 < 10;

    Todas esas tablas / vistas que referencias usando la coma (,) deberas usar el operador de union adecuado (INNER o OUTER JOIN).


    AMB

    Some guidelines for posting questions...

    AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas

    jueves, 6 de septiembre de 2018 15:33

Todas las respuestas

  • Hola Juan Manuel Pardo García:

    Vaya por delante desde mi opinión, que tu consulta para analizar y en dos motores diferentes, parece un "locurón".

    Pero porque no haces el LEFT JOIN contra la tabla, y luego el max, lo limitas en el where, ya que Oracle no te permite relacionarlo contra esa subconsulta.

    Por otro lado en la segunda parte que expones, el select * no vale, tienes que darle un alias a la tabla derivada

    LEFT JOIN (SELECT * FROM ……..) AS O  ON O.CAMPO =

    Un saludo

    jueves, 6 de septiembre de 2018 7:26
  • Estas mezclando el viejo y nuevo estilos de unir tablas:

    Viejo: select * from T1, T2 where ...

    Nuevo: select * from T1 inner join T2 on ...

    Aca la parte de tu query haciendo la mezcla:

        LEFT OUTER JOIN
        tgProveedor
        ON tcPresupuestoComisReclam.Proveedor = tgProveedor.Codigo
    	
        ,tcVeh
    
        LEFT OUTER JOIN
        tgPtoVenta
        ON tcVeh.Emp = tgPtoVenta.Emp
        AND  tcVeh.PuntoVenta = tgPtoVenta.PuntoVenta
    
    ...
    
        LEFT JOIN
        tmPSAOPVCliPedido
        ON tcVeh.NumPedidoFab = tmPSAOPVCliPedido.CAR
        AND  tmPSAOPVCliPedido.IdCliPedido = (
               SELECT
                    MAX(tmPSAOPVCliPedido.IdCliPedido)
               FROM
                    tmPSAOPVCliPedido
               WHERE
                    tmPSAOPVCliPedido.CAR = tcVeh.NumPedidoFab
        )
    	
    	,
        tcComisReclam,
        tgMarca,
        tgModelo,
        tgVersion
    
    WHERE
    ...

    Es importante que pongas atencion a esto, pues cuando usamos LEFT OUTER JOIN estamos diciendole a SQL Server que la tabla a preservar es la del lado izquierdo y que las columnas referenciadas del lado derecho que no machen una fila del lado izquierdo se usara la marca NULL.  Luego tu en la clausula WHERE referencias esas columnas pero como NULL no se puede comparar usando operadores como =, >, =>, etc. entonces estarias desechando esas filas.  La forma correcta es poniendo esas restricciones comoparte de la union.

    Ejemplo:

    select *
    from T1 left outer join T2 on T2.id = T1.id
    where T2.col2 < 10  -- <<<<< incorrecto

    select *
    from T1 left outer join T2 on T2.id = T1.id and T2.col2 < 10;

    Todas esas tablas / vistas que referencias usando la coma (,) deberas usar el operador de union adecuado (INNER o OUTER JOIN).


    AMB

    Some guidelines for posting questions...

    AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas

    jueves, 6 de septiembre de 2018 15:33