Obtenga los registros del mes pasado en SQL server


Quiero obtener los registros del mes pasado basados en mi campo [miembro] de la tabla de la base de datos "date_created".

¿Cuál es el sql para hacer esto?

Para aclaración, último mes-1/8/2009 a 31/8/2009

Si hoy es 3/1/2010, necesitaré obtener los registros del 1/12/2009 al 31/12/2009.

Author: Billy, 2009-09-15

17 answers

SELECT * 
FROM Member
WHERE DATEPART(m, date_created) = DATEPART(m, DATEADD(m, -1, getdate()))
AND DATEPART(yyyy, date_created) = DATEPART(yyyy, DATEADD(m, -1, getdate()))

Es necesario comprobar el mes y el año.

 81
Author: Dave Barker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-09 23:56:49

Todas las respuestas existentes (en funcionamiento) tienen uno de dos problemas:

  1. Ignorarán los índices en la columna que se está buscando
  2. La voluntad (potencialmente) seleccionar los datos que no se pretende, en silencio corromper sus resultados.

1. Índices ignorados:

En su mayor parte, cuando una columna que se busca tiene una función llamada a ella (incluso implícitamente, como para CAST), el optimizador debe ignorar los índices en la columna y buscar a través de cada registro. He aquí un ejemplo rápido:

Estamos tratando con marcas de tiempo, y la mayoría de los RDBMSs tienden a almacenar esta información como un valor creciente de algún tipo, generalmente un long o BIGINTEGER recuento de mili-/nanosegundos. El tiempo actual se ve/se almacena así:

1402401635000000  -- 2014-06-10 12:00:35.000000 GMT

No ves el valor 'Year' ('2014') ahí, ¿verdad? De hecho, hay un poco de matemáticas complicadas para traducir hacia adelante y hacia atrás. Así que si llama a cualquiera de las funciones de la parte extracción / fecha en el buscado columna, el servidor tiene que realizar todas esas matemáticas solo para averiguar si puede incluirlo en los resultados. En tablas pequeñas esto no es un problema, pero a medida que el porcentaje de filas seleccionadas disminuye, esto se convierte en un drenaje cada vez más grande. Entonces, en este caso, lo estás haciendo por segunda vez para preguntar sobre MONTH... bueno, te haces una idea.

2. Datos no deseados:

Dependiendo de la versión particular de SQL Server, y los tipos de datos de columna, usando BETWEEN (o similar rangos de límite superior inclusivos: <=) puede resultar en la selección de datos incorrectos . Esencialmente, puede terminar incluyendo datos de la medianoche del día "siguiente", o excluyendo alguna parte de los registros del día "actual".

Lo que tú deberías estar haciendo:

Así que necesitamos una forma que sea segura para nuestros datos, y usaremos índices (si es viable). El camino correcto es entonces de la forma:

WHERE date_created >= @startOfPreviousMonth AND date_created < @startOfCurrentMonth

Dado que solo hay un mes, @startOfPreviousMonth puede ser fácilmente sustituida por / derivada por:

DATEADD(month, -1, @startOCurrentfMonth)

Si necesita derivar el inicio del mes actual en el servidor, puede hacerlo a través de lo siguiente:

DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)

Una breve explicación aquí. La inicial DATEDIFF(...) obtendrá la diferencia entre el inicio de la era actual (0001-01-01 - AD, CE, lo que sea), esencialmente devolviendo un entero grande. Este es el conteo de meses hasta el inicio del mes actual . A continuación, añadimos este número al inicio de la era, que es en el inicio del mes.

Así que su script completo podría / debería ser similar a lo siguiente:

DECLARE @startOfCurrentMonth DATETIME
SET @startOfCurrentMonth = DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)

SELECT *
FROM Member
WHERE date_created >= DATEADD(month, -1, @startOfCurrentMonth) -- this was originally    misspelled
      AND date_created < @startOfCurrentMonth

Por lo tanto, todas las operaciones de fecha solo se realizan una vez, en un valor; el optimizador es libre de usar índices, y no se incluirán datos incorrectos.

 61
Author: Clockwork-Muse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-17 21:59:54

Agregue las opciones que se han proporcionado hasta ahora no usarán sus índices en absoluto.

Algo como esto hará el truco, y hará uso de un índice en la tabla (si existe).

DECLARE @StartDate DATETIME, @EndDate DATETIME
SET @StartDate = dateadd(mm, -1, getdate())
SET @StartDate = dateadd(dd, datepart(dd, getdate())*-1, @StartDate)
SET @EndDate = dateadd(mm, 1, @StartDate)

SELECT *
FROM Member
WHERE date_created BETWEEN @StartDate AND @EndDate
 12
Author: mrdenny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-05 19:19:32
DECLARE @StartDate DATETIME, @EndDate DATETIME
SET @StartDate = DATEADD(mm, DATEDIFF(mm,0,getdate())-1, 0)
SET @EndDate = DATEADD(mm, 1, @StartDate)

SELECT *
FROM Member
WHERE date_created BETWEEN @StartDate AND @EndDate

Una actualización a la solución de mrdenny, de esta manera obtendrá exactamente el mes pasado desde YYYY-MM-01

 8
Author: Rokas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-20 07:45:21

Una forma de hacerlo es usando la función DATEPART :

select field1, field2, fieldN from TABLE where DATEPART(month, date_created) = 4 
and DATEPART(year, date_created) = 2009

Devolverá todas las fechas en abril. Para el mes pasado (es decir, anterior al mes actual) puede usar GETDATE y DATEADD también:

select field1, field2, fieldN from TABLE where DATEPART(month, date_created) 
= (DATEPART(month, GETDATE()) - 1) and 
DATEPART(year, date_created) = DATEPART(year, DATEADD(m, -1, GETDATE()))
 2
Author: Vinko Vrsalovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-15 03:50:06

El último mes considere como hasta el último día del mes. 31/01/2016 aquí el último día del mes sería el 31 de enero. que no es similar a los últimos 30 días.

SELECT CONVERT(DATE, DATEADD(DAY,-DAY(GETDATE()),GETDATE()))
 2
Author: M2012,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-12 12:20:58
select * from [member] where DatePart("m", date_created) = DatePart("m", DateAdd("m", -1, getdate())) AND DatePart("yyyy", date_created) = DatePart("yyyy", DateAdd("m", -1, getdate()))
 1
Author: DmitryK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-15 03:48:03
DECLARE @StartDate DATETIME, @EndDate DATETIME    
SET @StartDate = DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0)    
SET @EndDate = dateadd(dd, -1, DATEADD(mm, 1, @StartDate))

SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate 

Y otra actualización a la solución de mrdenny.
También da el último día exacto del mes anterior.

 1
Author: Dorothy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-19 21:56:17
declare @PrevMonth as nvarchar(256)

SELECT @PrevMonth = DateName( month,DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0)) + 
   '-' + substring(DateName( Year, getDate() ) ,3,4)
 1
Author: sheetal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-15 22:18:24

Consulta SQL para obtener solo el registro del mes actual

SELECT * FROM CUSTOMER
WHERE MONTH(DATE) = MONTH(CURRENT_TIMESTAMP) AND YEAR(DATE) = YEAR(CURRENT_TIMESTAMP);
 1
Author: Mohammad Abraq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-11 18:21:20

En Sql server para el último mes:

select * from tablename 
where order_date > DateAdd(WEEK, -1, GETDATE()+1) and order_date<=GETDATE()
 0
Author: arunkumar.halder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-06 15:02:11
DECLARE @curDate INT = datepart( Month,GETDATE())
IF (@curDate = 1)
    BEGIN
        select * from Featured_Deal
        where datepart( Month,Created_Date)=12 AND datepart(Year,Created_Date) = (datepart(Year,GETDATE())-1)

    END
ELSE
    BEGIN
        select * from Featured_Deal
        where datepart( Month,Created_Date)=(datepart( Month,GETDATE())-1) AND datepart(Year,Created_Date) = datepart(Year,GETDATE())

    END 
 0
Author: Kranti Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-01 10:54:31
DECLARE @StartDate DATETIME, @EndDate DATETIME
SET @StartDate = dateadd(mm, -1, getdate())
SET @StartDate = dateadd(dd, datepart(dd, getdate())*-1, @StartDate)
SET @EndDate = dateadd(mm, 1, @StartDate)
set @StartDate = DATEADD(dd, 1 , @StartDate)
 0
Author: Pradeep Samaranayake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-15 15:08:37
WHERE 
    date_created >= DATEADD(MONTH, DATEDIFF(MONTH, 31, CURRENT_TIMESTAMP), 0)
    AND date_created < DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
 0
Author: Kostya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-01 01:06:28

Soy de Oracle env y lo haría así en Oracle:

select * from table
where trunc(somedatefield, 'MONTH') =
trunc(sysdate -INTERVAL '0-1' YEAR TO MONTH, 'MONTH')

Idea: Estoy ejecutando un informe programado del mes anterior (desde el día 1 hasta el último día del mes, no con ventana). Esto podría ser un índice hostil, pero Oracle tiene un manejo rápido de la fecha de todos modos. ¿Existe una forma similar simple y corta en MS SQL? La respuesta que compara el año y el mes por separado parece tonta para la gente de Oracle.

 0
Author: ant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-15 07:49:44

Puede obtener los registros del último mes con esta consulta

SELECT * FROM dbo.member d 
WHERE  CONVERT(DATE, date_created,101)>=CONVERT(DATE,DATEADD(m, datediff(m, 0, current_timestamp)-1, 0)) 
and CONVERT(DATE, date_created,101) < CONVERT(DATE, DATEADD(m, datediff(m, 0, current_timestamp)-1, 0),101) 
 0
Author: Shahin Al Kabir Mitul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-27 14:56:44

La forma en que solucioné un problema similar fue agregando Mes a mi SELECCIONAR porción

Month DATEADD(day,Created_Date,'1971/12/31') As Month

Y que he añadido DONDE declaración

Month DATEADD(day,Created_Date,'1971/12/31') = month(getdate())-1
 0
Author: Kalenji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-30 09:38:13