2012-03-29 125 views
9

Tengo un paquete ssis que se ejecuta en días hábiles (lunes a viernes). si recibo un archivo el martes, en segundo plano (DB), toma la fecha del día hábil anterior y realiza algunas transacciones. Si ejecuto el trabajo el viernes, tiene que buscar la fecha de los lunes y procesar las transacciones.Cómo obtener el día hábil anterior en una semana con el día hábil actual utilizando el servidor sql

he utilizado la consulta a continuación para obtener la fecha anterior negocio

Select Convert(varchar(50), Position_ID) as Position_ID, 
     TransAmount_Base, 
     Insert_Date as InsertDate 
    from tblsample 
Where AsOfdate = Dateadd(dd, -1, Convert(datetime, Convert(varchar(10), '03/28/2012', 101), 120)) 
Order By Position_ID 

si ejecuto esta consulta voy a conseguir los resultados de ayer Transactios. si ejecuté la misma consulta el lunes, tiene que buscar las transacciones de los viernes en lugar de los domingos.

Respuesta

33
SELECT DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE()) 
         WHEN 'Sunday' THEN -2 
         WHEN 'Monday' THEN -3 
         ELSE -1 END, DATEDIFF(DAY, 0, GETDATE())) 

Yo prefiero usar DATENAME para cosas como esta DATEPART más, ya que elimina la necesidad de establecer DATEFIRST y asegura que las variaciones en la configuración de hora/fecha en máquinas locales no afectan los resultados. Finalmente, DATEDIFF(DAY, 0, GETDATE()) eliminará la parte de tiempo de GETDATE(), eliminando la necesidad de convertir a varchar (mucho más lento).


EDITAR (casi 2 años en)

Esta respuesta fue muy temprano en mi carrera y SO me molesta cada vez que se pone upvoted porque ya no estoy de acuerdo con el sentimiento de utilizar DATENAME.

Una solución mucho más rubust sería:

SELECT DATEADD(DAY, CASE (DATEPART(WEEKDAY, GETDATE()) + @@DATEFIRST) % 7 
         WHEN 1 THEN -2 
         WHEN 2 THEN -3 
         ELSE -1 
        END, DATEDIFF(DAY, 0, GETDATE())); 

Esto funcionará para todo el lenguaje y la configuración DATEFIRST.

+0

Usando 'DATENIDO' para evitar tener que saber' DATEFIRST', pero completando ignorando que es un idioma específico? –

+0

Muy bien Sin embargo, he encontrado más escenarios donde los conflictos DATEFIRST han sido un problema que los escenarios donde los conflictos de lenguaje han sido un problema. Por ejemplo, si crearas una UDF en tu base de datos no podrías definir la fecha primero dentro de la UDF, usted dependería de la consulta que llama a la función para establecer la fecha correcta (o no establecer una fecha diferente), es Es más probable que un usuario deba establecer una fecha diferente que establecer un idioma diferente (en mi experiencia). – GarethD

+1

Para seguir elaborando, solía trabajar en una empresa donde la semana de comisiones se ejecuta de miércoles a martes para ventas de papel, y de viernes a jueves para ventas por cable. Podríamos usar las mismas consultas para informar esto estableciendo la fecha en primer lugar. cualquier uso de DATEPART (DAY, [date]) para identificar los fines de semana inútiles. Es por eso que ** prefiero ** usar el nombre de la fecha. No defiendo que sea perfecto. – GarethD

0
select 
    dateadd(dd, 
      case DATEPART(dw, getdate()) 
      when 1 
      then -2 
      when 2 
      then -3 
      else -1 
     end, GETDATE()) 
+0

Uso de 'DATEPART (dw ...' sin conocer el entorno 'DATEFIRST' es [ambiguo] (http: //msdn.microsoft.com/en-us/library/ms174420.aspx). No lo haga. –

1

La solución más simple para encontrar el día hábil anterior es usar un calendar table con una columna llamada IsBusinessDay o algo similar. La consulta es algo como esto:

select max(BaseDate) 
from dbo.Calendar c 
where c.IsBusinessDay = 0x1 and c.BaseDate < @InputDate 

El problema con el uso de las funciones es que cuando (no si) usted tiene que crear excepciones por cualquier motivo (fiestas nacionales, etc.) el código rápidamente se convierte en imposible de mantener; con la tabla, solo UPDATE un valor único. Una tabla también hace que sea mucho más fácil responder preguntas como "cuántos días hábiles hay entre las fechas X e Y", que son bastante comunes en las tareas de informes.

3

Entonces, ¿qué:

declare @dt datetime='1 dec 2012' 

select case when [email protected]@DATEFIRST=DATEPART(dw,@dt) 
      then DATEADD(d,-2,@dt) 
     when ([email protected]@DATEFIRST)%7=DATEPART(dw,@dt)%7 
      then DATEADD(d,-3,@dt) 
     else DATEADD(d,-1,@dt) 
    end 
0

gracias por los consejos anteriores, que tenían una ligera variante en la consulta en la que mi usuario necesita todos los valores de la fecha hábil anterior. Por ejemplo, hoy es lunes y necesita todo entre el último viernes a medianoche y el sábado a medianoche. Hice esto usando un combo de lo anterior, y "entre", solo si alguien está interesado. No soy un gran técnico.

-- Declare a variable for the start and end dates. 
declare @StartDate as datetime 
declare @EndDate as datetime 

SELECT @StartDate = DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE()) 
WHEN 'Sunday' THEN -2 
WHEN 'Monday' THEN -3 
    ELSE -1 END, DATEDIFF(DAY, 0, GETDATE())) 
select @EndDate = @StartDate + 1 
select @StartDate , @EndDate 
-- Later on in the query use "between" 
and mydate between @StartDate and @EndDate 
1

Usted puede hacer esto una llamada a la función, la adición de un segundo parámetro para reemplazar GetDate() con cualquier fecha que quería. Funcionará para cualquier día de la semana, en cualquier rango de fechas, si cambia GetDate(). No va a cambiar la fecha si el día de la semana es la fecha de entrada (GetDate())

Declare @DayOfWeek As Integer = 2 -- Monday 

Select DateAdd(Day, ((DatePart(dw,GetDate()) + (7 - @DayOfWeek)) * -1) % 7, Convert(Date,GetDate())) 
Cuestiones relacionadas