在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_numberwhen 条件将缺失周的收入列设置为 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中列的值之间创建行的主要内容,如果未能解决你的问题,请参考以下文章

如何修改表SQL中列中的值

SQL Server 表未显示表中列的值

计算两个连续日期之间的唯一 ID,它们是 PySpark 中列的值

从行创建/透视列并创建透视后,我想在 SQL 中新创建的列中添加不同列的值

如何将sqlalchemy中列的默认值设置为关系中列的值?

列存储索引中列的顺序在 SQL Server 2012 中是不是重要