假设我有一张这样的桌子:
subscriber_id | package_id | package_start_date | package_end_date | package_price_per_day |
---|---|---|---|---|
1081 | 231 | 2014-01-13 | 2014-12-31 | $3. |
1084 | 231 | 2014-03-21 | 2014-06-05 | $3 |
1086 | 235 | 2014-06-21 | 2014-09-09 | $4 |
现在我想要基于 2014 年每个月总收入的前 3 个套餐的结果。 注意:例如,对于包 231 收入应计算为例如 1 月的 18 天 * $3 + 2 月的 28 天 * $3 + .... 等等。 对于第二行,计算方法与第一行相同(三月的 9 天* $3 + 四月的 30 天 * $3 ....) 在结果上,包应按月分组,并根据总收入显示排名。
示例结果:
月 | Package_id | 收入 | 排名 |
---|---|---|---|
一月 | 231. | 69499 | 1. |
一月 | 235. | 34345. | 2. |
一月 | 238. | 23455. | 3. |
二月 | 231. | 89274 | 1. |
我写了一个查询来过滤日期,以便我在 2014 年全年获得活跃订阅者(因为最初有不同年份的值),它显示了问题中的第一个表,但我不知道我该怎么做打破之后的几个月和几天。
select subscriber_id, package_id, package_start_date, package_end_date
from (
select subscriber_id, package_id
, case when year(package_start_date) < '2014' then package_start_date = '01-Jan-2014' else package_start_date end as package_start_date
, case when year(package_start_date) > '2014' then package_end_date = '31-Dec-2014' else package_start_date end as package_end_date
, price_per_day
from subscription
) a
where year(package_start_date) = '2014' and year(package_end_date) = '2014'
请不要强调语法 - 我只是想了解 SQL 中的逻辑方法。
答案 0 :(得分:0)
假设你有一个表格,它是一个名为 d 的列中的唯一日期列表,该表格名为 d
然后就比较简单了
SELECT *
FROM t
INNER JOIN d on d.d >= t.package_start_date AND d.d < t.package_end_date
假设您将 1 月 1 日的开始日期和 1 月 2 日的结束日期分类为 1 天。如果你分类为两个,使用 <=
这将导致您的包裹行乘以天数,因此 1 月 1 日和 1 月 11 日的开始和结束天数意味着该行重复 10 次。每行的 d.d 日期都不同,您可以从 d.d 中提取月份,然后对其进行分组,以便为您提供每个包裹每个月的总数
假设您已经将上面的查询作为 x 进行了 CTE,就像
SELECT DATEPART(month, x.dd), --the d.d date
package_id,
SUM(revenue)
FROM x
GROUP BY DATEPART(month, x.dd), package_id
因为当连接到 d 时,T 中的行会被笛卡尔爆炸重复,所以您可以安全地将它们分组或聚合以将它们恢复为每个包每月的单个值。如果您有一年以上的包裹,您还应该按日期分组,以避免混淆从 2020 年 1 月到 2021 年 2 月的包裹中的月份(它们会停留两个一月和两个二月)
然后你需要做的就是添加收入的排名,看起来它会在第一步中加入
RANK(DATEDIFF(DAY, start, end)*revenue) OVER(PARTITION BY package_id)
我认为我正确地理解您根据整个期间而不是每月的总收入对套餐进行排名..也请查看排名和密集排名之间的差异,因为您可能想要密集排名