【问题标题】:SQL Query to only pull one record for first day of month, for every monthSQL查询每月的第一天只提取一条记录,每个月
【发布时间】:2018-07-17 13:38:50
【问题描述】:

我有一张每天有一条记录的表。例如。 (这只是表格的日期列)

2018-07-08 03:00:00
2018-07-07 03:00:00
2018-07-06 03:00:00
2018-07-05 03:00:00
2018-07-04 03:00:00
2018-07-03 03:00:00
2018-07-02 03:00:00
2018-07-01 03:00:00
2018-06-30 03:00:00
2018-06-29 03:00:00

这些数据可以追溯到几年前

我只想提取表中所有月份的第一天记录。

执行此操作的 SQL 是什么?

(在 SQL Server 2014 上)

【问题讨论】:

  • DATEPART(天,数据) = 1
  • 与这里的一些答案相比,我更喜欢使用日历表并构建开始/结束范围,但如果有的话,每天一行不会有很大的性能优势(并且会造成很大的维护损失)

标签: sql sql-server tsql


【解决方案1】:

我会使用day() 函数:

select t.*
from t
where day(t.MyDate) = 1;

这和 datepart() 都不是 ANSI/ISO 标准,但还有其他支持 day() 的数据库。标准函数是extract(day from t.MyDate)

如果您想要每个月的表中的第一条记录——但对于某些月份,那可能不是第一天——那么您可以使用row_number()。一种方法是:

select top (1) with ties t.*
from t
order by row_number() over (partition by year(mydate), month(mydate) order by day(mydate) asc);

【讨论】:

  • ...为什么不只是ORDER BY myDate?这也将涵盖给定日期有多行的情况。
  • @Clockwork-Muse 。 . .因为这会返回每个月最近的第一天。
  • 显然它确实如此,就像按基准日期本身排序一样,因为它已经分区了。我只是想知道是否有理由选择一个而不是另一个?
【解决方案2】:

如果您的所有时间都归零,那么您只需要获取DATEPART 第一天的所有内容。

select * from dbo.MyTable mt where DATEPART(day, mt.MyDate) = 1

如果您每天有一行,它将起作用。当然,如果您每天有超过一行,则需要使用 DISTINCT 或聚合。

【讨论】:

    【解决方案3】:

    你可以使用row_number()函数:

    select *
    from (select *, row_number() over (partition by datepart(year, date), datepart(month, date) order by datepart(day, date)) seq
          from table
         ) t
    where seq = 1;
    

    也许您还需要在partition 子句中使用year

    【讨论】:

    • 请注意,这将获取每月的第一天当前,这不一定是该月的实际第一天。此外,它会压缩所有年份,并为每个月提供一个不确定的行。
    【解决方案4】:

    虽然已经回答了这个问题,但您也可以在 MS SQL 中使用部分日期。

      create table  #temp (dates date) 
    
     insert into #temp values  ('2018-01-02'),('2018-01-05'), ('2018-01-09'), ('2018-01-10')
    
     select * from #temp 
    
     dates
     2018-01-02
     2018-01-05
     2018-01-09
     2018-01-10
    
     You can use this to get beginning of the month 
    
         select DATEFROMPARTS(year(dates), month(dates), 01) Beginningofmonth  from #temp 
         group by DATEFROMPARTS(year(dates), month(dates), 01)
    
     Output: 
     Beginningofmonth
     2018-01-01
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-12
      • 2020-10-02
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多