【问题标题】:SQL Query to retrieve users based on date and monthSQL查询根据日期和月份检索用户
【发布时间】:2018-09-05 11:34:47
【问题描述】:

我有下表:

用户

  • 用户 ID
  • 公司ID
  • 姓名
  • 活跃
  • 加入日期
  • Date_Left

我正在尝试获取可计费用户的查询,标准是:

  • 加入计费月份的用户不会被视为计费用户。
  • 在计费当月离开的用户计费用户。

我有以下疑问:

SELECT * from user u WHERE CompanyID = 1205
AND (p.IsActive = 1 AND MONTH(p.Date_Joined) != MONTH(GETDATE())
OR (p.is_active = 0 AND MONTH(p.Date_Left) = MONTH(GETDATE())

问题是此查询不起作用,因为它不检查用户的年份(2017 年 9 月加入的用户不被视为可计费,即使他们应该在 2017 年而不是今年加入,不应将 2018 年 9 月创建的人员视为可计费)。

如何实现年份或优化我的查询?

【问题讨论】:

    标签: sql sql-server tsql date datetime


    【解决方案1】:

    EOMONTH 可用于确定月份的最后一天。例如:

    /* last day of prev month */ EOMONTH('2018-09-05', -1) = 2018-08-31
    /* last day of curr month */ EOMONTH('2018-09-05')     = 2018-09-30
    

    您可以轻松地检查活跃用户是否在上个月加入或非活跃用户在当月离开,如下所示:

    DECLARE @billdate AS DATE = '2018-09-05';
    
    SELECT * 
    FROM user
    WHERE CompanyID = 1205 AND (
        (
            IsActive = 1 AND 
            Date_Joined <= EOMONTH(@billdate, -1)
        )
        OR
        (
            IsActive = 0 AND 
            Date_Left >  EOMONTH(@billdate, -1) AND
            Date_Left <= EOMONTH(@billdate)
        )
    )
    

    【讨论】:

    • 感谢您的询问,但如果我在我的桌子上启动它,我不会得到本月离开的人(因此仍然可以计费)。如果人在GETDATE()月份离开,需要计费
    • 谢谢,这看起来不错,但我想知道如何测试它以模拟不同的发票月份,我是否增加 -1 以模拟以后的月份?
    • -1 不应被触摸。将GETDATE() 替换为用户变量,例如DECLARE @billdate AS DATE = '2018-01-01'; 并将所有 GETDATE() 实例替换为 @billdate
    • 太棒了!这开始看起来很完美!问题是即使使用WHERE CompanyID=1205-clause,我也从其他公司获得用户,这是否意味着我需要为每个子句添加AND CompanyID = 1205
    • OR 条件应括在括号中。现在是CompanyID=1205 AND Condition1 OR Condition2。应该是CompanyID ... AND (Condition1 or Condition2)
    【解决方案2】:
    • 我认为您的括号已关闭。将它们放在AND 周围没有任何作用。您可能想将它们放在OR 周围。
    • 别名p 没有目标表。从列名来看,我认为以它为前缀的列也是来自user,所以将别名改为u
    • 要查看年份,您可以使用 year(),类似于您使用 month() 的方式。


    SELECT *
           FROM user u
           WHERE u.companyid = 1205
                 AND (u.isactive = 1
                      AND month(p.date_joined) != month(getdate())
                      AND year(p.date_joined) = year(getdate())
                       OR u.is_active = 0
                          AND month(p.date_left) = month(getdate())
                          AND year(p.date_left) = year(getdate()));
    

    【讨论】:

      【解决方案3】:

      我认为您需要检查当前月份的开始日期和结束日期。 试试这个

      DECLARE @D_FROM_DATE DATE,@D_TO_DATE DATE
      
      SELECT @D_FROM_DATE=DATEADD(DAY,-DATEPART(DAY,GETDATE()-1),GETDATE()),
      @D_TO_DATE=DATEADD(MONTH,1,DATEADD(DAY,-DATEPART(DAY,GETDATE()),GETDATE()))
      
          SELECT * FROM USER P
          WHERE P.COMPANYID = 1205
          AND 
          (
              CAST(P.DATE_JOINED AS DATE) BETWEEN  @D_FROM_DATE AND @D_TO_DATE
              OR 
              CAST(P.DATE_LEFT AS DATE) BETWEEN  @D_FROM_DATE AND @D_TO_DATE
          )
      

      【讨论】:

        【解决方案4】:

        你可以这样使用

        SELECT * from user u WHERE CompanyID = 1205
        AND (p.IsActive = 1 AND CONCAT(YEAR(p.Date_Joined),'/',MONTH(p.Date_Joined)) != CONCAT(YEAR(GETDATE()),'/',MONTH(GETDATE())))
        OR (p.is_active = 0 AND CONCAT(YEAR(p.Date_Left),'/',MONTH(p.Date_Left)) = CONCAT(YEAR(GETDATE()),'/',MONTH(GETDATE())))
        

        【讨论】:

          猜你喜欢
          • 2021-10-08
          • 1970-01-01
          • 2017-03-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多