Spark SQL - 如何对链接到特定日期的日期范围内的值求和
Spark SQL - How to SUM values over date range linked to a especific date
我需要对与该日期相关的最近 30 天(不含)的值求和,包括每个商店中的每个产品。
假设所有月份都是 30 天:
date|store|product|values
2020-06-30|Store1|Product1|1
2020-07-02|Store1|Product2|4
2020-07-01|Store2|Product1|3
2020-07-18|Store1|Product1|4
2020-07-18|Store1|Product2|2
2020-07-18|Store2|Product1|2
2020-07-30|Store1|Product1|1
2020-08-01|Store1|Product1|1
2020-08-01|Store1|Product2|1
2020-08-01|Store2|Product1|6
在 day 2020-08-01 的行中,将 (2020-08-20 - 30 days) 的值与 2020-08-19 的值相加并将其放入 2020-08-20 行,如下所示:
(第一行不包括 '2020-06-30' 因为是 30 多天前和 '2020-08-01' 因为是同一天,并且继续......)
date|store|product|sum_values_over_last_30_days_to_this_date
2020-08-01|Store1|Product1|5
2020-08-01|Store1|Product2|6
2020-08-01|Store2|Product1|5
....
在下面尝试过这个,但什么也没有:
spark.sql("""
SELECT
a.date,
a.store,
a.product,
SUM(a.values) OVER (PARTITION BY a.product,a.store ORDER BY a.date BETWEEN a.date - INTERVAL '1' DAY AND a.date - INTERVAL '30' DAY) AS sum
FROM table a
""").show()
有人可以帮助我吗?
这是我对示例数据框的试用。
+----------+------+--------+------+
| date| store| product|values|
+----------+------+--------+------+
|2020-08-10|Store1|Product1| 1|
|2020-08-11|Store1|Product1| 1|
|2020-08-12|Store1|Product1| 1|
|2020-08-13|Store1|Product2| 1|
|2020-08-14|Store1|Product2| 1|
|2020-08-15|Store1|Product2| 1|
|2020-08-16|Store1|Product1| 1|
|2020-08-17|Store1|Product1| 1|
|2020-08-18|Store1|Product1| 1|
|2020-08-19|Store1|Product2| 1|
|2020-08-20|Store1|Product2| 1|
|2020-08-21|Store1|Product2| 1|
|2020-08-22|Store1|Product1| 1|
|2020-08-21|Store1|Product1| 1|
|2020-08-22|Store1|Product1| 1|
|2020-08-20|Store1|Product2| 1|
|2020-08-21|Store1|Product2| 1|
|2020-08-22|Store1|Product2| 1|
+----------+------+--------+------+
df.withColumn("date", to_date($"date"))
.createOrReplaceTempView("table")
spark.sql("""
SELECT
date,
store,
product,
COALESCE(SUM(values) OVER (PARTITION BY 1 ORDER BY date RANGE BETWEEN 3 PRECEDING AND 1 PRECEDING), 0) as sum
FROM table
""").show()
+----------+------+--------+---+
| date| store| product|sum|
+----------+------+--------+---+
|2020-08-10|Store1|Product1|0.0|
|2020-08-11|Store1|Product1|1.0|
|2020-08-12|Store1|Product1|2.0|
|2020-08-13|Store1|Product2|3.0|
|2020-08-14|Store1|Product2|3.0|
|2020-08-15|Store1|Product2|3.0|
|2020-08-16|Store1|Product1|3.0|
|2020-08-17|Store1|Product1|3.0|
|2020-08-18|Store1|Product1|3.0|
|2020-08-19|Store1|Product2|3.0|
|2020-08-20|Store1|Product2|3.0|
|2020-08-20|Store1|Product2|3.0|
|2020-08-21|Store1|Product2|4.0|
|2020-08-21|Store1|Product1|4.0|
|2020-08-21|Store1|Product2|4.0|
|2020-08-22|Store1|Product1|6.0|
|2020-08-22|Store1|Product1|6.0|
|2020-08-22|Store1|Product2|6.0|
+----------+------+--------+---+
你可以尝试self-join
而不是window函数,也许这种join
会起作用-
SELECT
a.date,
a.store,
a.product,
SUM(IFNULL(b.value,0))
FROM
table a
LEFT JOIN
(
SELECT
a.date,
a.store,
a.product,
a.value
FROM
table a
)b
ON
a.store = b.store
AND
a.product = b.product
AND
a.date > b.date - INTERVAL 30 DAYS
AND a.date <= b.date
GROUP BY
1,2,3
确保对内部查询的值求和,直到今天才求和。
我需要对与该日期相关的最近 30 天(不含)的值求和,包括每个商店中的每个产品。 假设所有月份都是 30 天:
date|store|product|values
2020-06-30|Store1|Product1|1
2020-07-02|Store1|Product2|4
2020-07-01|Store2|Product1|3
2020-07-18|Store1|Product1|4
2020-07-18|Store1|Product2|2
2020-07-18|Store2|Product1|2
2020-07-30|Store1|Product1|1
2020-08-01|Store1|Product1|1
2020-08-01|Store1|Product2|1
2020-08-01|Store2|Product1|6
在 day 2020-08-01 的行中,将 (2020-08-20 - 30 days) 的值与 2020-08-19 的值相加并将其放入 2020-08-20 行,如下所示: (第一行不包括 '2020-06-30' 因为是 30 多天前和 '2020-08-01' 因为是同一天,并且继续......)
date|store|product|sum_values_over_last_30_days_to_this_date
2020-08-01|Store1|Product1|5
2020-08-01|Store1|Product2|6
2020-08-01|Store2|Product1|5
....
在下面尝试过这个,但什么也没有:
spark.sql("""
SELECT
a.date,
a.store,
a.product,
SUM(a.values) OVER (PARTITION BY a.product,a.store ORDER BY a.date BETWEEN a.date - INTERVAL '1' DAY AND a.date - INTERVAL '30' DAY) AS sum
FROM table a
""").show()
有人可以帮助我吗?
这是我对示例数据框的试用。
+----------+------+--------+------+
| date| store| product|values|
+----------+------+--------+------+
|2020-08-10|Store1|Product1| 1|
|2020-08-11|Store1|Product1| 1|
|2020-08-12|Store1|Product1| 1|
|2020-08-13|Store1|Product2| 1|
|2020-08-14|Store1|Product2| 1|
|2020-08-15|Store1|Product2| 1|
|2020-08-16|Store1|Product1| 1|
|2020-08-17|Store1|Product1| 1|
|2020-08-18|Store1|Product1| 1|
|2020-08-19|Store1|Product2| 1|
|2020-08-20|Store1|Product2| 1|
|2020-08-21|Store1|Product2| 1|
|2020-08-22|Store1|Product1| 1|
|2020-08-21|Store1|Product1| 1|
|2020-08-22|Store1|Product1| 1|
|2020-08-20|Store1|Product2| 1|
|2020-08-21|Store1|Product2| 1|
|2020-08-22|Store1|Product2| 1|
+----------+------+--------+------+
df.withColumn("date", to_date($"date"))
.createOrReplaceTempView("table")
spark.sql("""
SELECT
date,
store,
product,
COALESCE(SUM(values) OVER (PARTITION BY 1 ORDER BY date RANGE BETWEEN 3 PRECEDING AND 1 PRECEDING), 0) as sum
FROM table
""").show()
+----------+------+--------+---+
| date| store| product|sum|
+----------+------+--------+---+
|2020-08-10|Store1|Product1|0.0|
|2020-08-11|Store1|Product1|1.0|
|2020-08-12|Store1|Product1|2.0|
|2020-08-13|Store1|Product2|3.0|
|2020-08-14|Store1|Product2|3.0|
|2020-08-15|Store1|Product2|3.0|
|2020-08-16|Store1|Product1|3.0|
|2020-08-17|Store1|Product1|3.0|
|2020-08-18|Store1|Product1|3.0|
|2020-08-19|Store1|Product2|3.0|
|2020-08-20|Store1|Product2|3.0|
|2020-08-20|Store1|Product2|3.0|
|2020-08-21|Store1|Product2|4.0|
|2020-08-21|Store1|Product1|4.0|
|2020-08-21|Store1|Product2|4.0|
|2020-08-22|Store1|Product1|6.0|
|2020-08-22|Store1|Product1|6.0|
|2020-08-22|Store1|Product2|6.0|
+----------+------+--------+---+
你可以尝试self-join
而不是window函数,也许这种join
会起作用-
SELECT
a.date,
a.store,
a.product,
SUM(IFNULL(b.value,0))
FROM
table a
LEFT JOIN
(
SELECT
a.date,
a.store,
a.product,
a.value
FROM
table a
)b
ON
a.store = b.store
AND
a.product = b.product
AND
a.date > b.date - INTERVAL 30 DAYS
AND a.date <= b.date
GROUP BY
1,2,3
确保对内部查询的值求和,直到今天才求和。