2012-03-01 12 views
5

Tengo un procedimiento almacenado que extrae datos y se une a los datos del año pasado en la Fecha. El problema es que los datos del año actual no tienen nada para unirse porque no hubo 29 de febrero de 2011. ¿Alguien más ha experimentado este problema? ¿Alguien tiene alguna idea sobre cómo solucionarlo?29 de febrero en comparación con el 28 de febrero del año anterior

Aquí es el procedimiento almacenado:

SELECT 
--b.Date_Rep AS Date_Rep, 
SUM(b.AccountsCreatedThisYear) AS AccountsCreatedThisYearTot, 
SUM(a.AccountsCreatedThisYear) AS AccountsCreatedLastYearTot, 

FROM Report2011.dbo.T_Report_01 b WITH (NOLOCK) --This year  
LEFT JOIN Report2011.dbo.T_Report_01 a WITH (NOLOCK) ON DATEADD(yyyy,-1,b.Date_Rep) = a.date_rep --Last year 
WHERE (a.Date_Rep BETWEEN DATEADD(year, -1,@StartDate) AND DATEADD(year, -1,@EndDate)) 
+0

Por qué 'IZQUIERDA JOIN' cuando la cláusula' WHERE' obligará a que se convierta en una unión interna? 'DATEADD' no puede crear fechas inválidas, entonces ¿el problema es que * se * une, pero a la fecha" incorrecta "o qué? –

+0

¿no sería esto simplemente compararlo con el 1 de marzo del año pasado? – Greg

+1

@ J.B. Estoy con J Copper: ya comparas este año 28 al año pasado 28, así que no hay fecha en la que puedas comparar los datos de este año 29 a. – Filburt

Respuesta

0
declare @29Feb datetime = convert(datetime,'2012/02/29') 
    declare @28Feb datetime = convert(datetime,'2012/02/28') 

select case when 
      dateadd(yy,-1,@29Feb) = dateadd(yy,-1,@28Feb) 
      then 1 
      else 0 end 

Esta instrucción de selección las salidas 1, por lo que en realidad la FEB 29 y febrero 28 fechas tienen sólo una fecha correspondiente en el último año, febrero 28.

Ahora está haciendo una suma para dos períodos en años diferentes por lo que sucede que el primer período tiene 1 día menos que el período actual.
Cómo le podría responder a la siguiente pregunta:

"How many accounts have been created in the last year's February and how many this year?" 

¿Es importante el hecho tuvo mes de febrero de 28 días y los otros 29? No lo creo, la referencia es febrero, no los días.

lo tanto, veo dos problemas con esta consulta:

  • Puede haber un día este año, cuando no se han creado las cuentas, pero en el último año, en el mismo período, algunas cuentas lo hizo, por lo que la left join no capta los del año pasado
  • Para este año para dos fechas diferentes, 28 y 29 corresponden solo a un día, 28 por lo que este se suma dos veces.


SELECT  (SUM(b.AccountsCreatedThisYear) 
    FROM Report2011.dbo.T_Report_01 WITH (NOLOCK) --This year 
    WHERE Date_Rep BETWEEN @StartDate and @EndDate) as AccountsCreatedThisYearTot, 

    (SUM(b.AccountsCreatedThisYear) 
    FROM Report2011.dbo.T_Report_01 WITH (NOLOCK) -- Last Year 
    WHERE Date_Rep BETWEEN DATEADD(year, -1,@StartDate) AND DATEADD(year, -1,@EndDate)) as AccountsCreatedLastYearTot 
1

Trate de usar un FULL OUTER JOIN en lugar de un LEFT JOIN y utilizar COALESCE:

SUM(COALESCE(b.AccountsCreatedThisYear, 0)) AS AccountsCreatedThisYearTot y SUM(COALESCE(a.AccountsCreatedThisYear, 0)) AS AccountsCreatedLastYearTot

por lo que evitar el NULL de cuando las fechas no coinciden .

4

Para empezar, no haría una cláusula where en las columnas de una tabla en el lado externo de una combinación izquierda. Prueba de esto, en su lugar:

SELECT SUM(b.AccountsCreatedThisYear) AS AccountsCreatedThisYearTot, 
     SUM(a.AccountsCreatedThisYear) AS AccountsCreatedLastYearTot, 
FROM Report2011.dbo.T_Report_01 b WITH (NOLOCK) --This year  
LEFT JOIN Report2011.dbo.T_Report_01 a WITH (NOLOCK) 
     ON DATEADD(yyyy,-1,b.Date_Rep) = a.date_rep --Last year 
WHERE b.Date_Rep BETWEEN @StartDate AND @EndDate 
+1

Sí, estaba convirtiendo su unión izquierda en una unión interna. – HLGEM

0

No hubo Feb 29 años pasado, pero 1 de marzo fue hace 365 días y 28 Feb fue hace 366 días.

SELECT SUM(b.AccountsCreatedThisYear) AS AccountsCreatedThisYearTot, 
    SUM(a.AccountsCreatedThisYear) AS AccountsCreatedLastYearTot, 
FROM Report2011.dbo.T_Report_01 b WITH (NOLOCK) --This year  
LEFT JOIN Report2011.dbo.T_Report_01 a WITH (NOLOCK) 
    ON DATEADD(dd,-365,b.Date_Rep) = a.date_rep --Last year 
WHERE b.Date_Rep BETWEEN @StartDate AND @EndDate 

+1 Marcos Bannister como lo hacía su sintaxis

Cuestiones relacionadas