有一个事务处理表,其中包含2006年至2019年的日期数据,其中每个月(销售量)的记录数量为零到很多。要求是一条SQL语句,该语句每月获取我过去十二个月的销售总额以及包含值的不同月份的总数。
下面是到目前为止的SQL(有点混乱,因为日期保存在单独的表中,并且日期必须来自批处理)
WITH monthly_totals AS
(SELECT
sum(t1.[Transaction_totals]) AS sum_of_sales,
CASE
WHEN t2.month_id % 100 < 10 AND t2.month_id/100 < 10 THEN CONCAT('200', t2.month_id % 100, '-0', t2.month_id / 100, '-01')
WHEN t2.month_id % 100 < 10 AND t2.month_id/100 >= 10 THEN CONCAT('200', t2.month_id % 100, '-', t2.month_id / 100, '-01')
WHEN t2.month_id % 100 >= 10 AND t2.month_id/100 < 10 THEN CONCAT('20', t2.month_id % 100, '-0',t2. month_id / 100, '-01')
ELSE CONCAT('20', t2.month_id % 100, '-', t2.month_id / 100, '-01')
END as date,
t2.month_id
FROM
TRANSACTION t1
INNER JOIN
BATCH t2 ON t1.batch_id = t2.batch_id
GROUP BY
CASE
WHEN t2.month_id % 100 < 10 AND t2.month_id/100 < 10 THEN CONCAT('200', t2.month_id % 100, '-0', t2.month_id / 100, '-01')
WHEN t2.month_id % 100 < 10 AND t2.month_id/100 >= 10 THEN CONCAT('200', t2.month_id % 100, '-', t2.month_id / 100, '-01')
WHEN t2.month_id % 100 >= 10 AND t2.month_id/100 < 10 THEN CONCAT('20', t2.month_id % 100, '-0',t2. month_id / 100, '-01')
ELSE CONCAT('20', t2.month_id % 100, '-', t2.month_id / 100, '-01')
END,
t2.month_id
)
SELECT
sum(sum_of_sales) AS sum_of_sales,
count(distinct month_id) as month_count,
date
FROM
monthly_totals
WHERE
date IN (select distinct month_id
from
vw_dimDate as d
where
date >= (
select
distinct(date)
from
dimDate
where
month_id = month_id
and dayNumber = 1) - 365
and
date <= (
select
distinct(date)
from
dimDate
where
month_id = month_id
and dayNumber = 1
)
)
GROUP BY
date
但这会引发以下错误: 子查询返回的值超过1。当子查询遵循=,!=,<,<=,>,> =或将子查询用作表达式时,不允许这样做。
对于一个跨越13年的表,最终产品应该是这样的:
2006-01-01:$ 2,382,823 [2005年1月1日至2006年1月1日的销售总额],1 [交易的月份数不同]
2006-02-01 $ 4,382,823 [2005年2月1日至2006年2月1日的销售总额],2 [交易月数不同]
2006-03-01 $ 4,382,823 [从2005-03-01开始的总销售额-2006-03-01],3 [交易月份数不同]
... 2010-01-01:23,323,204美元[2009年1月1日至2010年1月1日的销售总和],12个[交易月份数不同]
2011-01-01:12,938,823美元(2009年2月1日至2010年2月1日的销售总额),12个[交易月数不同]
等... 表格中的每个月
答案 0 :(得分:1)
只是想知道是否有一个驱动它的日期表并将其连接到交易表是否更好,那么您应该能够使用前12个月的总和分区,并计算交易<> 0 ...如果...加入下面的表格。
此网站上的其他人可能会肯定知道这是否可行。
with years as (
select * from
(values(2006),(2007),(2008),(2009),(2010),(2011),(2012),(2013),(2014),(2015),(2016),(2017),(2018),(2019)
) as t (Year_id))
,months as (
select * from
(values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
) as t (month_id))
select Year_id,month_id,0 as [Transaction_totals]
from years
cross join months
order by 1,2
答案 1 :(得分:0)
根据Roger Clerkwell的建议,我将首先使用With With Block(CTE)创建一个Dates表,然后在其余的查询中使用。这样一来,您便可以根据从日期表中拉回的日期来查询数据。
由于我正在使用Oracle数据库,因此我的解决方案说明了如何创建一个日期表,该表为输入到查询中的日期范围生成一个月开始日期的列表。它还可以产生月份的结束日期,但是,我意识到,对于这个问题,不需要月份的结束日期。我在其中使用了无数报告。通过一些小的调整,如果您需要每天查询结果,并且完全了解CONNECT BY LEVEL
之后,此代码也可以产生不同的结果。
SELECT TRUNC(ADD_MONTHS('01-JUL-18', LEVEL-1), 'MM') START_DATE,
LAST_DAY(ADD_MONTHS('01-JUL-18', LEVEL-1)) END_DATE
FROM DUAL CONNECT BY LEVEL <= CEIL(MONTHS_BETWEEN('30-JUN-19', '01-JUL-18'))
;
SQL Server不需要利用dual
表。如果您对双重表格有疑问,请参见THIS Stackoverflow问题。
答案 2 :(得分:0)
WITH CTE AS (
SELECT 2006 AS Year
UNION ALL
SELECT Year + 1 FROM CTE WHERE Year < 2019
),CTE2 AS (
SELECT 1 AS Month
UNION ALL
SELECT Month + 1 FROM CTE2 WHERE Month < 12
)
select dateadd(mm,datediff(mm,-1,dateadd(year,-1,convert(varchar,year)+'- '+convert(varchar,Month)+'-'+'1')),-1)start_Date,
dateadd(mm,datediff(mm,-1,convert(varchar,year)+'-'+convert(varchar,Month)+'- '+'1'),-1)End_Date
from CTE
cross join CTE2
order by 1
OPTION (MAXRECURSION 0)
答案 3 :(得分:0)
谢谢Roger,Stuphan和Stark博士的建议。昨天,我对交叉连接并不熟悉,所以继续走另一条路,找到了替代解决方案。但是,在查看日期表后,您已经看到了有关创建方法的示例,如果我今天要重新执行此操作,则可以采用这种方法。作为记录,这就是我如何解决的:(基本上使用两次相同的每月总计数据集,这允许第一个数据集提供日期,而第二个数据集提供滚动的年度平均值) / p>
每月(总计)AS
(选择
sum(t1。[Transaction_totals])AS sum_of_sales,
t5.date,
product_id,
t1.store_id
从 交易t1
内部联接 批处理t2开启t1.batch_id = t2.batch_id
内部联接 vw_dimDate t5 ON t4.month_id = t5.month_id AND t4.year = t5.year AND t5.dayNumber = 1
组别 t5.date, product_id, t1.store_id ),年总计为( 选择 t1.date, t1.store_id, t1.product_id, sum(t2.sum_of_sales)AS sum_of_sales, 计数(与t2.date截然不同)为month_count
从 每月总计t1
内部联接 t2.date> DATEADD(年,-1,CONVERT(DATE,t1.date))AND t2.date <= CONVERT(DATE,t1.date)AND t1.store_id = t2.store_id AND t1.product_id = t2.product_id
组别 t1.date, t1.store_id, t1.product_id
) 选择 日期, store_id, product_id, sum_of_sales / month_count * 12作为sum_of_sales, month_count
订购 t1.date, store_id, product_id