sql新手,无法解决以下问题,但对于经验丰富的用户来说可能很简单。我有一张优秀的钱币表,我需要将它分成每月一桶;该表格包含以下列:
Name, amount_due, date_due.
我需要将信息除以' date_due'分为5个不同的月盆,当月,上个月,2个月,3个月,> 3个月大。
答案 0 :(得分:2)
我假设您在每月执行SUM
的摘要数据之后,而不是按月显示所有行。
name , amount_due, date_due
Alice , 100, 2017-09-10
Bob , 500, 2017-07-03
Charlie, 300, 2017-07-02
Dan , 150, 2017-04-01
Eve , 200, 2017-01-01
Faith , 50, 2017-09-13
此查询将date_due
值转换为“月”值(同时仍保留date
或datetime
类型信息),然后按月汇总:
输出:
sum_amount_due, month_due
150, 2017-09-01
800, 2017-07-01
150, 2017-04-01
200, 2017-01-01
SQL:
SELECT
SUM( amount_due ) AS sum_amount_due,
DATEADD( month, DATEDIFF( month, 0, date_due ), 0 ) AS month_due
FROM
your_table
GROUP BY
DATEADD( month, DATEDIFF( month, 0, date_due ), 0 )
ORDER BY
month_due
此查询不会特别处理3个月以上的日期,因此我们需要更改month_due
表达式,以便在3个月以前的日期返回'2001-01-01'
:
输出:
sum_amount_due, month_due
150, 2017-09-01
800, 2017-07-01
350, 2000-01-01
SQL:
SELECT
SUM( amount_due ) AS sum_amount_due,
CASE
WHEN date_due < DATEADD( month, GETDATE(), -3 ) THEN '2000-01-01'
ELSE DATEADD( month, DATEDIFF( month, 0, date_due ), 0 )
END AS month_due
FROM
your_table
GROUP BY
CASE
WHEN date_due < DATEADD( month, GETDATE(), -3 ) THEN '2000-01-01'
ELSE DATEADD( month, DATEDIFF( month, 0, date_due ), 0 )
END
ORDER BY
month_due
由于SQL的工作原理,您需要在SELECT
和GROUP BY
子句中重复获取月份表达式。
通过使用子查询识别超过3个月的记录,可以在语法上略微简化:
SELECT
SUM( amount_due ) AS sum_amount_due,
CASE
WHEN month_due_3_months THEN '2000-01-01'
ELSE month_due
END AS month_due
FROM
(
SELECT
amount_due,
DATEADD( month, DATEDIFF( month, 0, date_due ), 0 ) AS month_due,
CASE
WHEN DATEADD( month, DATEDIFF( month, 0, date_due ), 0 ) < DATEADD( month, GETDATE(), -3 ) THEN 1
ELSE 0
END AS month_due_3_months
FROM
your_table
) AS all_months
GROUP BY
CASE
WHEN month_due_3_months THEN '2000-01-01'
ELSE month_due
END AS month_due
ORDER BY
month_due
语法复杂性是由于SQL语言中固有的一些约束:
SELECT
子句(“投影”)在 FROM
AND GROUP BY
子句后进行评估,因此您无法引用别名表达式在GROUP BY
中:您必须重复它们或在子查询中指定它们。Get month as date value
功能,令人惊讶的是,您必须使用DATEADD( month, DATEDIFF( month, 0, @dateValue ), 0 )
。
GETMONTH
或DATEPART
,因为它只返回月份组件而忽略年份值,因此会错误地对来自同一月份的不同年份的行进行分组。CASE WHEN x THEN y ELSE z END
构造(尽管有COALESCE
,NULLIF
和ISNULL
,但这些是特殊情况) 答案 1 :(得分:1)
我假设所有期间都是累积的,否则你需要修改每个条件。如果这符合预期或需要修改,请告诉我。
select name
,sum( case when datediff(day,getdate(),date_due)<day(date_due) then amount_due end) 'current month'
,sum( case when datediff(month,getdate(),date_due)<=1 then amount_due end) 'last month'
,sum( case when datediff(month,getdate(),date_due)<=2 then amount_due end) 'last two month'
,sum( case when datediff(month,getdate(),date_due)<=3 then amount_due end) 'last three month'
,sum( case when datediff(month,getdate(),date_due)>3 then amount_due end) 'more than three month'
from monies
group by name
答案 2 :(得分:0)
用例来确定到期月份之间的due_date
SELECT name,
amount_due,
due_date,
CASE WHEN CAST(due_date AS DATETIME) BETWEEN DATEADD(mm, -1, GETDATE()) AND DATEADD(mm, 0, GETDATE())
THEN 'this month'
WHEN CAST(due_date AS DATETIME) BETWEEN DATEADD(mm, -2, GETDATE()) AND DATEADD(mm, -1, GETDATE())
THEN 'last month'
WHEN CAST(due_date AS DATETIME) BETWEEN DATEADD(mm, -3, GETDATE()) AND DATEADD(mm, -2, GETDATE())
THEN '2 months old'
WHEN CAST(due_date AS DATETIME) BETWEEN DATEADD(mm, -4, GETDATE()) AND DATEADD(mm, -3, GETDATE())
THEN '3 months old'
WHEN CAST(due_date AS DATETIME) < DATEADD(mm, -4, GETDATE())
THEN '> 3 months old'
END month_of_due