我有两张桌子" Fiscal_calendar"和"销售"。这两个表没有链接在一起。我希望能够编写一个查询,根据财务日历计算一周内的总销售额。这可能吗?我们的财政日历从12月1日开始,每个月结束于星期五。
任何帮助都将不胜感激。
Fiscal_calendar
Period Period1_StartDate Period1_EndDate Period2_StartDate Period2_EndDate...........
2018 01/12/2017 29/12/2017 30/01/2018 26/01/2018
Sales
Sales_order_no Amount Date Customer
111 20453 03/12/2017 abc
112 23154 04/12/2017 bbb
113 20201 10/12/2017 ddd
114 39012 11/12/2017 ccc
115 11111 18/12/2017 eee
116 22222 25/12/2017 uuu
所以在第1期startdate和enddate之间有4周的时间。前两个销售额下降到第1周。因此第1周的总销售额将为43607
输出
WEEK Total_Sales
W1 43607
W2 59213
W3 11111
W4 22222
答案 0 :(得分:1)
CROSS APPLY
的两种用途是将财务日历表中的(规范化)修复为有用的内容,然后是简单的GROUP BY
。
WHERE
子句从会计日历中选择行,即派生视图中的句点或周(或其他)。
如果当周没有销售,则LEFT JOIN
。
ON
子句查看会计日历和周派生视图,以防派生视图描述的那一周不是真正的那一周。
SELECT
p.year_id,
p.period_id,
w.week_id,
SUM(s.amount) AS total_amount
FROM
fiscal_calendar c
CROSS APPLY
(
SELECT period, 1, period1_startDate, period1_endDate
UNION ALL SELECT period, 2, period2_startDate, period2_endDate
..
UNION ALL SELECT period, 13, period13_startDate, period13_endDate
)
AS p(year_id, period_id, startDate, endDate)
CROSS APPLY
(
SELECT 1, DATEADD(d, 0, startDate), DATEADD(d, 6, startDate)
UNION ALL SELECT 2, DATEADD(d, 7, startDate), DATEADD(d, 13, startDate)
UNION ALL SELECT 3, DATEADD(d, 14, startDate), DATEADD(d, 20, startDate)
UNION ALL SELECT 4, DATEADD(d, 21, startDate), DATEADD(d, 27, startDate)
)
AS w(week_id, startDate, endDate)
LEFT JOIN
sales s
ON s.date BETWEEN c.period1_startdate AND c.period13_enddate
AND s.date BETWEEN w.startDate AND w.endDate
WHERE
p.year_id = 2018
AND p.period_id = 1
GROUP BY
p.year_id,
p.period_id,
w.week_id
答案 1 :(得分:1)
UNPIVOT
是一个有用的TSQL运算符,用于规范化数据。基本上它需要一行并创建新行 - 列中列中指定的每列一个。
在下面的情况下,我在PeriodX_StartDate列上进行了忽略。我最初做了两个非活动,另一个在PeriodX_EndDate上。结束日期是不必要的,但是如果你想知道我是如何加入这两个univots的:我使用交叉应用来生成每周的密钥,并且有一个谓词,测试它们是否相等。如果没有谓词,您将获得笛卡尔积。
为了生成周,我使用了与@MatBailie的答案非常相似的CROSS APPLY,除了我通过为每周生成一组参数来避免工会,这些参数被传递到生成日期的函数中。
WITH normalizedCal AS (
SELECT [Period], MonthStart, WeekKey, StartDate, CutoffDate
FROM fiscal_calendar cal
UNPIVOT (
MonthStart FOR StartKey IN (Period1_StartDate, Period2_StartDate, ..., PeriodN_StartDate)
) AS startInfo
CROSS APPLY (
SELECT 'WK' + CAST((StartIndex / 7) + 1 AS char(1)) [WeekKey]
, DATEADD(day, startIndex, MonthStart) [StartDate]
, DATEADD(day, EndIndex, MonthStart) [CutoffDate]
FROM (
VALUES ( 0, 7 ), ( 7, 14 ), ( 14, 21 ), ( 21, 28 )
) rangeValues ( StartIndex, EndIndex )
) weekInfo
)
SELECT [Period], MonthStart, WeekKey, COALESCE(SUM(AMOUNT), 0) [Total_Sales]
FROM normalizedCal nc
LEFT JOIN sales ON sales.Date >= nc.StartDate AND sales.Date < nc.CutoffDate
GROUP BY [Period], MonthStart, WeekKey
ORDER BY [Period], MonthStart, WeekKey
包含样本数据的工作示例:
WITH normalizedCal AS (
SELECT [Period], MonthStart, WeekKey, StartDate, CutoffDate
FROM (
VALUES (2018, '2017-12-01', '2017-12-29', '2017-12-30', '2018-01-26')
) cal ([Period], Period1_StartDate, Period1_EndDate, Period2_StartDate, Period2_EndDate)
UNPIVOT (
MonthStart FOR StartKey IN (Period1_StartDate, Period2_StartDate)
) AS startInfo
CROSS APPLY (
SELECT 'WK' + CAST((StartIndex / 7) + 1 AS char(1)) [WeekKey]
, DATEADD(day, startIndex, MonthStart) [StartDate]
, DATEADD(day, EndIndex, MonthStart) [CutoffDate]
FROM (
VALUES ( 0, 7 ), ( 7, 14 ), ( 14, 21 ), ( 21, 28 )
) rangeValues ( StartIndex, EndIndex )
) weekInfo
),
sales AS (
SELECT [Sales_order_no],[Amount], CAST([Date] as DATE) [Date],[Customer]
FROM (VALUES
(111, 20453, '2017-12-03', N'abc'),
(112, 23154, '2017-12-04', N'bbb'),
(113, 20201, '2017-12-10', N'ddd'),
(114, 39012, '2017-12-11', N'ccc'),
(115, 11111, '2017-12-18', N'eee'),
(116, 22222, '2017-12-25', N'uuu')
) [salessrc] ( [Sales_order_no],[Amount],[Date],[Customer])
)
SELECT [Period], MonthStart, WeekKey, COALESCE(SUM(AMOUNT), 0) [Total_Sales]
FROM normalizedCal nc
LEFT JOIN sales ON sales.Date >= nc.StartDate AND sales.Date < nc.CutoffDate
GROUP BY [Period], MonthStart, WeekKey
ORDER BY [Period], MonthStart, WeekKey