根据加入日期和剩余日期选择用户

时间:2018-09-07 08:05:06

标签: sql sql-server algorithm datetime

我有下表:

人员

UserID Name Date_Joined Date_Left 
1      Test  2018-08-10 NULL
2      Test2 2018-07-10 NULL
3      Test3 2018-07-10 2018-12-31
4      Test4 2018-08-10 2018-09-10

我只想按他们的加入日期和/或离职日期检查他们是否可开票(=有效)。

这些是可计费的用户:

  1. 开始月份为账单日期前至少一个月的用户  没有剩余日期

  2. 开始月份为账单日期前至少一个月的用户  左月的日期等于开票日期或晚于  帐单日期

计费月份= 总是上个月。

我使用以下查询:

DECLARE @billdate AS DATE = '2018-09-01';
SELECT * 
FROM person
WHERE CompanyID = 1205 AND (
    (
        date_joined <= EOMONTH(@billdate, -1)
    )
    OR
    (
        date_left >  EOMONTH(@billdate, -1) AND
        date_left <= EOMONTH(@billdate)
    )
)

我的问题:

  • 如果我将帐单日期设置为2018-11-01,则用户Test4仍在表中。
  • 如果我将billdate设置为2019-01-01,用户Test3就会消失

查询出了什么问题,我该如何优化呢?

样本数据:

用户列表:

1-测试-2018-08-10-空

2-Test2-2018-07-10-NULL

3-Test3-2018-07-10-2018-12-31

4-Test4-2018-08-10-2018-09-10

对于上个月(= 8/8月)的计费期= @billdate 2018-09-10,这些是计费用户:

Test2 测试3

但是,当我将计费周期更改为10月10日时,这些是可计费用户:

测试 测试2 测试3

2 个答案:

答案 0 :(得分:3)

如果我正确理解您的逻辑,则计费用户是指其开始月份至少比当前月份早一个月,并且结束月份小于或等于当前月份的用户。

SELECT *,
    CASE WHEN @billdate >= DATEADD(d, 1, EOMONTH(date_joined)) AND
              (@billdate <= DATEADD(d, 1, EOMONTH(date_left)) OR date_left IS NULL)
         THEN 'billable'
         ELSE 'not billable' END AS status
FROM person;

这种计费逻辑似乎与客户获得第一个月的免费服务是一致的,但是从第二个月到最后一个月都是可计费的。

Demo

答案 1 :(得分:0)

使用make标志将加入月份和年份与帐单月份和年份进行比较,并为每个用户创建一个标志,然后使用子查询进行过滤

  select * from t
(
 select *,case when (month(date_joined)=month(billdate) 
   and  year(date_joined)=year(billdate)) then 'N' else 'Y' end as flag_billable
  from user
) as t where t.flag_billable='Y'

查询

DECLARE @billdate AS DATE = '2018-09-01';
select * from 
(
    SELECT * ,case when (month(date_joined)=month(@billdate) 
           and  year(date_joined)=year(@billdate)) then 'N' else 'Y' end as  flag_billable
    FROM person
) t where t.flag_billable='Y'