DÓNDE Cláusula para encontrar todos los registros en un mes específico


84

Quiero poder darle a un procedimiento almacenado un mes y un año y que devuelva todo lo que sucede en ese mes, ¿cómo hago esto ya que no puedo comparar, ya que algunos meses tienen diferentes números de días, etc.?

¿Cuál es la mejor manera de hacer esto? ¿Puedo pedir comparar según el año y el mes?

Gracias.

Respuestas:


181

Creo que la función que estás buscando es MONTH(date). Probablemente también quieras usar 'AÑO' .

Supongamos que tiene una tabla llamada thingsque se parece a esto:

id happend_at
-- ----------------
1  2009-01-01 12:08
2  2009-02-01 12:00
3  2009-01-12 09:40
4  2009-01-29 17:55

Y digamos que desea ejecutar para buscar todos los registros que tienen un happened_atdurante el mes 2009/01 (enero de 2009). La consulta SQL sería:

SELECT id FROM things 
   WHERE MONTH(happened_at) = 1 AND YEAR(happened_at) = 2009

Que volvería:

id
---
1
3
4

13
En efecto ! Para cualquiera que esté interesado, "Las funciones DÍA, MES y AÑO son sinónimos de DATEPART (dd, date), DATEPART (mm, date) y DATEPART (aa, date), respectivamente".
Tarks

15

El uso de las funciones MES y AÑO como se sugiere en la mayoría de las respuestas tiene la desventaja de que SQL Server no podrá usar ningún índice que pueda haber en su columna de fecha. Esto puede acabar con el rendimiento en una mesa grande.

Me inclinaría a pasar un valor DATETIME (por ejemplo, @StartDate) al procedimiento almacenado que representa el primer día del mes que le interesa.

Luego puede usar

SELECT ... FROM ...
WHERE DateColumn >= @StartDate 
AND DateColumn < DATEADD(month, 1, @StartDate)

Si debe pasar el mes y el año como parámetros separados al procedimiento almacenado, puede generar un DATETIME que represente el primer día del mes usando CAST y CONVERT y luego proceda como se indicó anteriormente. Si hace esto, recomendaría escribir una función que genere un DATETIME a partir de valores enteros de año, mes y día, por ejemplo, lo siguiente de un blog de SQL Server .

create function Date(@Year int, @Month int, @Day int)
returns datetime
as
    begin
    return dateadd(month,((@Year-1900)*12)+@Month-1,@Day-1)
    end
go

La consulta entonces se convierte en:

SELECT ... FROM ...
WHERE DateColumn >= Date(@Year,@Month,1)
AND DateColumn < DATEADD(month, 1, Date(@Year,@Month,1))

1
Ya, estoy de acuerdo con @joe "El uso de las funciones MES y AÑO como se sugiere en la mayoría de las respuestas tiene la desventaja de que SQL Server no podrá usar ningún índice que pueda haber en su columna de fecha. Esto puede matar el rendimiento en una tabla grande . "
Raghav

¿Puedo agregar algo? Si está declarando '@StartDate en un parámetro, entonces yo también declararía' @EndDate y colocaría el DATEADD allí, en lugar de que SQL haga los cálculos en cada fila.
DataGirl

@DataGirl - punto interesante. Supuse que la función DATEADD se trataría como una constante de tiempo de ejecución y solo se evaluaría una vez. Si hay alguna duda sobre esto, declararlo @EndDatelo hará explícito.
Joe

3

Como alternativa a las funciones MONTH y YEAR, también funcionará una cláusula WHERE normal:

select *
from yourtable
where '2009-01-01' <= datecolumn and datecolumn < '2009-02-01'

3

Más un consejo muy sencillo. También puedes usar la función to_char , mira:

Por mes:

to_char ( sucedió_en , 'MM') = 01

Por año:
to_char ( sucedió_en , 'YYYY') = 2009

Por día:

to_char ( sucedió_en , 'DD') = 01

La función to_char es compatible con el lenguaje SQL y no con una base de datos específica.

Espero ayudar a alguien más ...

¡Abdominales!


1
Tengo la impresión de que esto solo funciona para Oracle, es realmente específico. SQL Server definitivamente no lo admite.
Carol


1

¿Puedo pedir comparar según el año y el mes?

Usted puede. Aquí hay un ejemplo simple usando la base de datos de muestra AdventureWorks ...

DECLARE @Year       INT
DECLARE @Month      INT

SET @Year = 2002
SET @Month = 6

SELECT 
    [pch].* 
FROM 
    [Production].[ProductCostHistory]   pch
WHERE
    YEAR([pch].[ModifiedDate]) = @Year
AND MONTH([pch].[ModifiedDate]) = @Month

1

Me resulta más fácil pasar un valor como un tipo de datos temporales (por ejemplo DATETIME) y luego usar la funcionalidad temporal, específicamente DATEADDy DATEPART, para encontrar las fechas de inicio y finalización del período, en este caso el mes, por ejemplo, esto encuentra la fecha de inicio y el par de fechas de finalización para el mes actual, simplemente reemplace CURRENT_TIMESTAMPsu parámetro de tipo DATETIME(tenga en cuenta que el valor 1990-01-01 es completamente arbitrario):

SELECT DATEADD(M, 
          DATEDIFF(M, '1990-01-01T00:00:00.000', CURRENT_TIMESTAMP), 
          '1990-01-01T00:00:00.000'), 
       DATEADD(M, 
          DATEDIFF(M, '1990-01-01T00:00:00.000', CURRENT_TIMESTAMP), 
          '1990-01-31T23:59:59.997')

0

Algo como esto debería hacerlo:

select * from yourtable where datepart(month,field) = @month and datepart(year,field) = @year

Alternativamente, puede dividir el mes y el año en sus propias columnas al crear el registro y luego seleccionarlas.

Iain


0

Una forma sería crear una variable que represente el primer día del mes (es decir, 1/5/2009), pasarla al proceso o compilarla (concatenar mes / 1 / año). Luego use la función DateDiff.

WHERE DateDiff(m,@Date,DateField) = 0

Esto devolverá cualquier cosa con un mes y año coincidentes.


-4
SELECT * FROM yourtable WHERE yourtimestampfield LIKE 'AAAA-MM%';

¿Dónde AAAAestá el año que quieres y MMes el mes que quieres?

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.