在sql中列的值之间创建行
Posted
技术标签:
【中文标题】在sql中列的值之间创建行【英文标题】:Create rows between values of column in sql 【发布时间】:2019-08-29 14:10:45 【问题描述】:我有以下客户 sku 级别的数据集
Customer customer_name customer_category sku sku_name week revenue
1 abc dsas 221 test 201701 100
1 abc dsas 221 test 201704 90
1 abc dsas 222 new 201701 100
我需要根据上面一周的最大值和最小值创建行。
应为新行重新填充客户和 sku 属性(customer_name、customer_category、sku、sku_name),但新行的收入应为 0。
数据为客户-sku-week 级别。
输出如下所示:
Customer customer_name customer_category sku sku_name week revenue
1 abc dsas 221 test 201701 100*total 4 rows
1 abc dsas 221 test 201702 0
1 abc dsas 221 test 201703 0
1 abc dsas 221 test 201704 90
1 abc dsas 222 new 201701 100*total 1 row
我试图将上面的表格与一个可能具有所有周值的虚拟表格进行右连接。
我想知道如何为新行重新填充客户和 sku 属性,同时仍将收入保持为 0
【问题讨论】:
也就是说,考虑处理应用代码中数据显示的问题。 如果我理解正确的话,这段代码的重点是为每个 sku 查找并插入缺少的周数,由于没有任何收入而最初没有插入这些周数? 我认为主要问题/要点是通过在运行时在选择上生成记录来进行审查显示。@TygerTy 因为根据 ANSI/ISO 标准,SQL 表是 无序插入新记录是一个坏主意,因为您假设 mysql 按顺序存储表数据... 我自己其实是在想,就好像你插入一个新的表格行一样,它不像 excel 那样会把所有东西都搞砸。如果您有一个自动递增的字段,它将在表格底部插入下一个可能的id
。我相信,在您的post 中,您提到了这一点。所以你需要一些其他的方式来组织数据,可能是通过确保按周值排序。这可能需要一个非常复杂的查询,或者只做几个查询。
【参考方案1】:
在使用 DataFrame API 的 Spark SQL 中,这可以通过以下步骤完成:
-
使用窗口函数
lead
获取下周
使用 sequence
函数创建缺失周数的数组
使用explode_outer
分解数组
使用另一个窗口函数 row_number
和 when
条件将缺失周的收入列设置为 0。
假设数据仅在一年内(否则必须调整序列),查询可能如下所示(在 PySpark 中):
from pyspark.sql.functions import lead, row_number, col, sequence, expr, explode_outer, coalesce, when
from pyspark.sql import Window
w = Window.partitionBy('customer', 'sku').orderBy('week')
w2 = Window.partitionBy('customer', 'sku', 'week').orderBy('week_2')
result = (
df
.withColumn('next_week', lead('week').over(w))
.withColumn('missed', expr("sequence(week, next_week-1, 1)"))
.withColumn('week_2', explode_outer('missed'))
.withColumn('week_3', coalesce('week_2', 'week'))
.withColumn('r', row_number().over(w2))
.withColumn('revenue_2', when(~(col('r') == 1), 0).otherwise(col('revenue')))
.select(
'customer', 'customer_name', 'customer_category', 'sku', 'sku_name',
col('week_3').alias('week'),
col('revenue_2').alias('revenue')
)
)
result.show()
+--------+-------------+-----------------+---+--------+------+-------+
|customer|customer_name|customer_category|sku|sku_name|week |revenue|
+--------+-------------+-----------------+---+--------+------+-------+
|1 |abc |dsas |221|test |201701|100 |
|1 |abc |dsas |221|test |201702|0 |
|1 |abc |dsas |221|test |201703|0 |
|1 |abc |dsas |221|test |201704|90 |
|1 |abc |dsas |222|new |201701|100 |
+--------+-------------+-----------------+---+--------+------+-------+
我希望这是你需要的。
【讨论】:
以上是关于在sql中列的值之间创建行的主要内容,如果未能解决你的问题,请参考以下文章
计算两个连续日期之间的唯一 ID,它们是 PySpark 中列的值