【问题标题】:getting month from a table according to the selected month根据所选月份从表中获取月份
【发布时间】:2013-07-27 23:54:34
【问题描述】:

我正在尝试获取患者部门和每月的报告。我正在选择一个部门和月份。我怎样才能明智地只获得选定月份的记录部门。我正在尝试以下查询但不工作:

SELECT MONTH(select convert(varchar,creation_Date,105) from Patient_Ref_master)

【问题讨论】:

  • @BogdanSahlean : 只有当月的行
  • 什么是一个月:1968 年 8 月或 8 月?
  • 请注意,如果您当前(或将来)在 creation_Date 列上有索引,那么 the accepted answer 的效率会非常低。一旦你拥有超过一年的数据,它也不会像你认为的那样工作。开放式范围 as in Habo's answer 会更好地工作(即使接受的答案添加了 YEAR() 过滤器)。

标签: sql-server


【解决方案1】:

如果您想要一个月/年对,则以下查询将起作用:

select *
  from Patient_Ref_Master
  where Cast( '20130801' as Date ) <= Creation_Date and Creation_Date < Cast( '20130901' as Date )

它的优点是查询可以使用索引,因为它不需要对每一行进行计算。

在查询之前计算限制通常很有帮助,例如当前月份:

declare @Start as Date = DateAdd( month, DateDiff( month, 0, GetDate() ), 0 );
declare @End as Date = DateAdd( month, 1, @Start );
select *
  from Patient_Ref_Master
  where @Start <= Creation_Date and Creation_Date < @End

编辑:如果将比较运算符与布尔运算符随意组合在一起使用是压倒性的,我提供以下简化:

declare @Patient_Ref_Master as Table ( Id Int Identity, Creation_Date Date );
insert into @Patient_Ref_Master ( Creation_Date ) values
  ( '20130731' ), ( '20130801' ), ( '20130815' ), ( '20130831' ), ( '20130901' );
select * from @Patient_Ref_Master;

declare @Start as Date = DateAdd( month, DateDiff( month, 0, Cast( '20130829' as Date ) ), 0 );
declare @End as Date = DateAdd( month, 1, @Start );

-- Incomprehensible   WHERE   clause:
select *
  from @Patient_Ref_Master
  where @Start <= Creation_Date and Creation_Date < @End;

-- Simplified AB version:
with
  JustRight as (
    select *
      from @Patient_Ref_Master
      where Creation_Date in ( @Start ) ),
  NotTooLate as (
    select *
      from @Patient_Ref_Master
      where Sign( DateDiff( day, @End, Creation_Date ) ) in ( -1 ) ),
  NotTooSoon as (
    select *
      from @Patient_Ref_Master
      -- NB: Do NOT include zero in the set of matches. That would be too easy.
      where Sign( DateDiff( day, Creation_Date, @Start ) ) in ( -1 ) ),
  TheResult as (
    select *
      from JustRight
    union
    select *
      from NotTooLate
    intersect
    select *
      from NotTooSoon )
  select * from TheResult;

不,IN 没有作为比较运算符列在documentation 中。

【讨论】:

  • +1 但这是构造子句的一种奇怪方式 - 变量 = 变量和列
  • @AaronBertrand - 曾经有人看到BETWEEN 与某种日期/时间数据一起使用时感到很不舒服。我发现这是编写“介于”相关逻辑的一种相当清晰的方法,尤其是在处理混合的开/关间隔时。坦率地说,我无法区分右侧朝上的 &lt; 和倒置的一面。
  • (1) 我根本没有提议 BETWEEN - I hate BETWEEN for date range queries。但通常我们在左侧有列,在右侧有比较器,例如Creation_Date &gt;= @Start AND Creation_Date &lt; @End。我没有看到你经常使用的表格(并且觉得它不太合乎逻辑),所以我问了。 (2) 我想你知道我所说的倒置是什么意思。
【解决方案2】:
select * from Patient_Ref_master
where MONTH(creation_Date)=1 --target month here, JAN as example  

SQLFIDDLE
我还发现 similar question 可以在此线程中获得额外的解决方法以及 other answer

【讨论】:

  • 将 MONTH() 应用于列意味着永远不会使用索引查找。它还假设我们想要 2000 年 1 月、2001 年 1 月、2002 年 1 月等,而不是特定年份的 1 月。
猜你喜欢
  • 2014-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多