none
Problemas con "Where Case When..." RRS feed

  • Pregunta

  • Buenas noches.

    Pido de su valiosa colaboracion, para que me ayuden a resolver este problema en SQL.

    Actualmente estoy haciendo una consulta que me regresa los pagos recibidos con su respectiva tasa de cambio, con el que el pago fue realizado.

    Para ello lo hago de la siguiente forma:

    Este primer select me permite sacar las tasas de cambio sin ningun problema.
    Código:
    SELECT         
              E.sell_rate 
              FROM CURRENCY_EXCHANGE E, Cash_Receipt P
              WHERE 
              Convert(varchar(10),CONVERT(date,P.Create_Date,106),103) = 
              CASE 
              WHEN Convert(varchar(10),CONVERT(date,E.effective_date,106),103) = Convert(varchar(10),CONVERT(date,P.Create_Date,106),103)
                  THEN Convert(varchar(10),CONVERT(date,E.effective_date,106),103)
              ELSE
                  Convert(varchar(10),CONVERT(date,P.Create_Date,106),103)
              END
    


    El problema se origina, cuando hago este select y lo anido para sacar otra informacion de otras tablas-
    Código:
            Select C.Id,
           Convert(varchar(10),CONVERT(date,P.Create_Date,106),103) Create_Date,
           --- Incluyo la Tasa de Cambio---------------------------------------------------------------------------------------------------
    (  SELECT         
              E.sell_rate 
              FROM CURRENCY_EXCHANGE E
              WHERE 
              Convert(varchar(10),CONVERT(date,P.Create_Date,106),103) = 
              CASE 
              WHEN Convert(varchar(10),CONVERT(date,E.effective_date,106),103) = Convert(varchar(10),CONVERT(date,P.Create_Date,106),103)
                  THEN Convert(varchar(10),CONVERT(date,E.effective_date,106),103)
              ELSE
                  Convert(varchar(10),CONVERT(date,P.Create_Date,106),103)
              END  
              ) as Tasa
           ---------------------------------------------------------------------------------------------------------------------------------
          from Customer C, Cash_Receipt P, cash_receipt_line Det, Receivable R  
          where  
            C.ID = P.CUSTOMER_ID And
            P.Check_id = Det. Check_Id And
            P.Customer_Id = Det.Customer_Id And
            R.Invoice_Id = Det.Invoice_Id And
            P.Status = 'A'
          Group by C.Id, P.Create_Date
    
    En la primer consulta me regresa las tasas, pero cuando hago el anidado, no me regresa ningun registro.

    Que estare haciendo mal?

    Me podrian ayudar por favor.

    Desde ya muchas gracias, y cualquier duda favor avisar para poder ampliar.
    viernes, 23 de junio de 2017 0:51

Respuestas

  • Lo que tienes implementado es una combinación de tipo LEFT OUTER JOIN del cual podrías obtener mas de una fila, lo cual no es admitido porque en una columna -de la lista de selección- sólo se permite escribir un valor, no un conjunto de valores. 

    - Ejecuta la consulta:

    SELECT 
        E.sell_rate
    FROM 
        CURRENCY_EXCHANGE E
        LEFT JOIN Cash_Receipt P ON CONVERT(date, P.Create_Date) = CONVERT(date, E.effective_date)

    ¿Cuántas filas retorna? ¿más de una?, si es mas de una es evidente que obtengas un error por los motivos descritos al inicio de mi respuesta.

    SELECT 
        C.Id,
        CONVERT(varchar(10), CONVERT(date, P.Create_Date), 103) AS Create_Date,
        E.sell_rate AS Tasa
    FROM 
        CURRENCY_EXCHANGE E
        INNER JOIN Cash_Receipt P ON CONVERT(date, P.Create_Date) = CONVERT(date, E.effective_date)
    	   AND P.Status = 'A'
        INNER JOIN Customer C ON P.CUSTOMER_ID = C.ID
        INNER JOIN cash_receipt_line Det ON P.Check_id = Det.Check_Id
    	   AND P.Customer_Id = Det.Customer_Id
        INNER JOIN Receivable R ON Det.Invoice_Id = R.Invoice_Id
    GO


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    viernes, 23 de junio de 2017 5:13
  • Estimado Geovanny,

    En realidad no es incorrecto tomar una tasa de cambio de una fecha inmediata anterior si el organismo encargado de su divulgación no pública las tasas por tratarse de un día sábado, domingo o feriado, de hecho así sucede en Perú e imagino que la realidad no es distinta en otros países salvo se publique la tasa de cambio para todos los días de la semana.

    OP,

    Entonces la idea es definir un intervalo de fechas con una tasa de cambio válida, por ejemplo: entre el viernes y el domingo la tasa que se registra es la del día viernes:

    WITH CTE_CURRENCY_EXCHANGE AS
    (
        SELECT
    	   CONVERT(date, E.effective_date) AS StartDate,
    	   CONVERT(date, DATEADD(DAY, -1, LEAD(E.effective_date, 1, GETDATE()) 
    		  OVER(ORDER BY E.effective_date))) AS EndDate,
    	   E.sell_rate
        FROM
    	   CURRENCY_EXCHANGE E
    )
    SELECT 
        C.Id,
        CONVERT(varchar(10), CONVERT(date, P.Create_Date), 103) AS Create_Date,
        E.sell_rate AS Tasa
    FROM 
        CTE_CURRENCY_EXCHANGE E
        INNER JOIN Cash_Receipt P ON CONVERT(date, P.Create_Date) BETWEEN E.StartDate AND E.EndDate
    	   AND P.Status = 'A'
        INNER JOIN Customer C ON P.CUSTOMER_ID = C.ID
        INNER JOIN cash_receipt_line Det ON P.Check_id = Det.Check_Id
    	   AND P.Customer_Id = Det.Customer_Id
        INNER JOIN Receivable R ON Det.Invoice_Id = R.Invoice_Id
    GO


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    viernes, 23 de junio de 2017 23:56

Todas las respuestas

  • Lo que tienes implementado es una combinación de tipo LEFT OUTER JOIN del cual podrías obtener mas de una fila, lo cual no es admitido porque en una columna -de la lista de selección- sólo se permite escribir un valor, no un conjunto de valores. 

    - Ejecuta la consulta:

    SELECT 
        E.sell_rate
    FROM 
        CURRENCY_EXCHANGE E
        LEFT JOIN Cash_Receipt P ON CONVERT(date, P.Create_Date) = CONVERT(date, E.effective_date)

    ¿Cuántas filas retorna? ¿más de una?, si es mas de una es evidente que obtengas un error por los motivos descritos al inicio de mi respuesta.

    SELECT 
        C.Id,
        CONVERT(varchar(10), CONVERT(date, P.Create_Date), 103) AS Create_Date,
        E.sell_rate AS Tasa
    FROM 
        CURRENCY_EXCHANGE E
        INNER JOIN Cash_Receipt P ON CONVERT(date, P.Create_Date) = CONVERT(date, E.effective_date)
    	   AND P.Status = 'A'
        INNER JOIN Customer C ON P.CUSTOMER_ID = C.ID
        INNER JOIN cash_receipt_line Det ON P.Check_id = Det.Check_Id
    	   AND P.Customer_Id = Det.Customer_Id
        INNER JOIN Receivable R ON Det.Invoice_Id = R.Invoice_Id
    GO


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    viernes, 23 de junio de 2017 5:13
  • Hola, buenas tardes William.

    Primero agradezco tu apoyo para lograr solucionar este problema.

    Estoy revisando la consulta, y corre muy bien, únicamente tengo un problema, que es por el cual abrí este hilo y te explico.

    Actualmente, se dan casos en que los clientes realizan pagos  un dia domingo, sabado, o a veces en dias feriados, el problema radica que esos dias no tengo tasa de cambio (tasa que se ingresa manualmente en el sistema), y si quisiera convertir el pago a dolares, pues me encuentro con el problema que no tengo una tasa de referencia.

    Entonces, mi problema es que necesito tomar una fecha que si tenga tasa de cambio, y estaba pensando con el "case when" poder utilizar una fecha que si tenga tasa, para poder convertirlo posteriormente a dolares.

    Espero haberme explicado, ya que revisando tu consulta, los pagos que no coinciden con la fecha del CONVERT(date, P.Create_Date) = CONVERT(date, E.effective_date) no me los incluye, y para estos casos deseo tomar aunque sea la tasa anterior para su conversion a dolar.

    Desde ya muchas gracias por el apoyo.
    • Editado head777 viernes, 23 de junio de 2017 23:23
    viernes, 23 de junio de 2017 23:21
  • Sinceramente apreciable head777, este tipo de casos es donde te puedo decir que no intentas "arreglar" problemas de consistencia e integridad de datos con artilugios, es decir, ingresando tasas de cambios que no han sido oficialmente registradas para dichas fechas, por lo que considero que debes insister en que se ingresen las tasas cambiarias.

    "Oh, the wind, the wind is blowing,through the graves the wind is blowing,Freedom soon will come; then well come from the shadows".The Partisan(Leonard Cohen) Email: me[at]geohernandez.net Blog:www.geohernandez.net

    viernes, 23 de junio de 2017 23:42
  • Estimado Geovanny,

    En realidad no es incorrecto tomar una tasa de cambio de una fecha inmediata anterior si el organismo encargado de su divulgación no pública las tasas por tratarse de un día sábado, domingo o feriado, de hecho así sucede en Perú e imagino que la realidad no es distinta en otros países salvo se publique la tasa de cambio para todos los días de la semana.

    OP,

    Entonces la idea es definir un intervalo de fechas con una tasa de cambio válida, por ejemplo: entre el viernes y el domingo la tasa que se registra es la del día viernes:

    WITH CTE_CURRENCY_EXCHANGE AS
    (
        SELECT
    	   CONVERT(date, E.effective_date) AS StartDate,
    	   CONVERT(date, DATEADD(DAY, -1, LEAD(E.effective_date, 1, GETDATE()) 
    		  OVER(ORDER BY E.effective_date))) AS EndDate,
    	   E.sell_rate
        FROM
    	   CURRENCY_EXCHANGE E
    )
    SELECT 
        C.Id,
        CONVERT(varchar(10), CONVERT(date, P.Create_Date), 103) AS Create_Date,
        E.sell_rate AS Tasa
    FROM 
        CTE_CURRENCY_EXCHANGE E
        INNER JOIN Cash_Receipt P ON CONVERT(date, P.Create_Date) BETWEEN E.StartDate AND E.EndDate
    	   AND P.Status = 'A'
        INNER JOIN Customer C ON P.CUSTOMER_ID = C.ID
        INNER JOIN cash_receipt_line Det ON P.Check_id = Det.Check_Id
    	   AND P.Customer_Id = Det.Customer_Id
        INNER JOIN Receivable R ON Det.Invoice_Id = R.Invoice_Id
    GO


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    viernes, 23 de junio de 2017 23:56
  • Hola, buenas tardes Williams.

    Primeramente, te agradezco el tiempo que estas invirtiendo en ayudarme a resolver este problema.

    Para continuar te comento que no había respondido, derivado que he estado haciendo varias pruebas, en el sistema y todo funciona de maravilla, únicamente encontré una variante, que nuevamente quisiera acudir a su conocimiento para ver como solucionar.

    INNER JOIN Receivable R ON Det.Invoice_Id = R.Invoice_Id

    En este INNER obligo a que tiene que hacer match con una factura, pero me acabo de dar cuenta que por el mismo tema del diferencial cambiario que se va generando, el sistema se lleva esas diferencias a una cuenta contable, es decir:

    Tengo la factura Fxxxxx1 a un diferencial cambiario de $1.23 pero cuando el cliente realizo los abonos, el diferencial era mayor $1.25 entonces, dicha diferencia, el sistema a nivel de la tabla "cash_receipt_line" genera un insert, pero no lo asocia a ninguna Invoice_Id, pero si al Check_Id que es el numero de recibo que se esta generando.

    Al final tengo que la Fxxxxx1 se pago en un solo recibo, pero en la tabla "cash_receipt_line" tiene dos registros, uno relacionado a la factura, y el otro valor asociado a una cuenta contable. 

    Por lo tanto al querer cuadrar el recibo esta descuadrado, por que me falta el valor que esta relacionado a una cuenta contable.

    He encontrado en la tabla "cash_receipt_line" que cuando esto ocurre, se llena un campo que se llama "Applied_Type" con valores "G" o "O", pero... Como podría hacer la relación, para incluir esta situación.

    Espero haberme dado a entender, sin mas quedo a la espera y nuevamente muchas gracias.








    • Editado head777 martes, 27 de junio de 2017 0:19
    martes, 27 de junio de 2017 0:07
  • Hola William, buenas tardes.

    Primero antes que nada, quiero agradecerte todo el apoyo.

    Me ha servido muchísimo tu conocimiento en el tema, de hecho no había contestado por que he estado probando este script a nivel de varias compañías que están en diferentes países.

    A la vez, te quisiera comentar de una situación que se me dio este semana y te la quisiera compartir, para saber si me puedes guiar, para ver como administrarla y garantizar la calidad de la información, permite me explicarte. 

    En este semana, el día 15/08 es feriado en una sucursal que tenemos, por temas de fiestas municipales. 

    Pero por motivos de cumplimiento de objetivo, a ultima hora, decidieron trabajarlo, pero nadie ingreso la tasa de cambio de ese día, y realizaron facturación. El ERP tomo la tasa del día anterior (14/08).

    El problema se me dio, cuando saque el reporte el mismo día 15/08 pero no me incliyo las facturas realizadas ese día, revisando el código me llama la atencion esta parte, y creo que por aqui anda el asunto.

    CONVERT(date, DATEADD(DAY, -1, LEAD(E.effective_date, 1, GETDATE()) 

    Veo que aquí, a la fecha actual se le resta uno, por lo que el día 15/08 que fue hecha la facturación, y que no tenia tasa de cambio, con el GETDATE quedo en 14/08, por lo que no me incluyo la factura, y me di cuenta después con los vendedores.

    Como consideras puede ser la mejor forma de arreglar, este pequeño inconveniente, por que únicamente, esto me falta para dejar al 100% el script.

    Muchas gracias nuevamente por la ayuda.





    • Editado head777 miércoles, 16 de agosto de 2017 18:59
    miércoles, 16 de agosto de 2017 18:53
  • Dudo que el problema pase por la instrucción que adjuntas, de hecho lo que hace la instrucción es asegurarse que exista un límite superior, ya sea la fecha registrada o el mismo día en que se ejecuta la consulta. Para el caso que expones los límites fueron: 14/08/2017 (último día donde se registro un tipo de cambio) y 15/08/2017 (día en que se ejecutó la consulta), las ventas del día 15 tienen que intersectar con los extremos mencionados.


    Nuestra profesión exige tener pasión por resolver problemas de una manera óptima y eficiente.
    miércoles, 16 de agosto de 2017 22:45