【问题标题】:I have 3 rows per user, need to have one row (with 3 columns) per user instead我每个用户有 3 行,每个用户需要有 1 行(3 列)
【发布时间】:2022-01-22 14:54:43
【问题描述】:

我正在使用 CTE 创建一个表格,其中包含客户最早的 3 次购买以及该客户的购买总数。我使用下面的查询成功地做到了这一点,但它为每个用户显示了 3 行,其中第一个购买日期、第二个购买日期和第三个购买日期分别显示为单独的行。我试图将 3 个购买日期显示为列,而不是每个用户一行。

此表有数百行,因此我无法在代码中编写所需的用户 ID。有任何想法吗?有没有办法合并 3 个 CTE 或编写代码以将用户的最早付款日期、最早的第二个、最早的第三个和总金额作为列吐出。当前代码如下:

WITH cte_2
     AS (SELECT customer_id,
                payment_date,
                Row_number()
                  OVER (
                    partition BY customer_id
                    ORDER BY payment_date ASC) AS purchase_number
         FROM   payment)
SELECT cte_2.customer_id,
       cte_2.payment_date,
       cte_2.purchase_number,
       Count(payment_id) AS total_payments
FROM   payment
       INNER JOIN cte_2
               ON payment.customer_id = cte_2.customer_id
WHERE  purchase_number <= 3
GROUP  BY cte_2.customer_id,
          cte_2.payment_date,
          purchase_number
ORDER  BY customer_id ASC 

上面代码的当前输出:

首选输出:

【问题讨论】:

  • 你能给我们一个reproducible example,即输入/预期输出吗?
  • 刚刚添加,谢谢。基本上,是否可以限制 CTE 内的行/购买数量,以便我可以将它们联合起来?是否有可能以某种方式在 SELECT 中多次列出 purchase_number?
  • 您需要 SQL 解决方案还是 pandas 解决方案?
  • 感谢熊猫解决方案!你有什么方法知道如何在 SQL 中处理?试图弄清楚两者。
  • 不是我的专业领域,抱歉。然而,pivot 也存在于 SQL 中:docs.microsoft.com/en-us/sql/t-sql/queries/…

标签: sql pandas union common-table-expression


【解决方案1】:

使用 pandas 你可以使用 pivot:

df = df.set_index('customer_id')
pivot_df = df.pivot(columns='purchase_number', values='payment_dates')
# To improve readability of your columns you can add a prefix:
pivot_df = pivot_df.add_prefix('payment_') 
pivot_df.merge(df['total_payments'], left_index=True, right_index=True).drop_duplicates()

使用时:

df = pd.DataFrame({
    'customer_id':[1,1,1,2,2,2,3],
    'payment_dates':['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05', '2021-01-06', '2021-01-01'],
    'purchase_number':[1,2,3,1,2,3,1], 
    'total_payments':[4,4,4,26,26,26,1]}) 

我们的结果是:

                payment_1   payment_2   payment_3   total_payments
customer_id             
1               2021-01-01  2021-01-02  2021-01-03  4
2               2021-01-04  2021-01-05  2021-01-06  26
3               2021-01-01  NaN         NaN         1

【讨论】:

    【解决方案2】:

    如果您的 sql 产品支持“case when”,那么您可以这样做:

    WITH 
      cte_2
         AS (SELECT payment_id,
                    Row_number()
                      OVER (
                        partition BY customer_id
                        ORDER BY payment_date ASC) AS purchase_number
             FROM   payment)
    SELECT pmt.customer_id,
           Count(case when cte_2.purchase_number=1 then 1 else null end) as [First Payment],
           Count(case when cte_2.purchase_number=2 then 1 else null end) as [2nd Payment],
           Count(case when cte_2.purchase_number=3 then 1 else null end) as [3rd Payment],
           Count(pmt.payment_id) AS total_payments
    FROM   payment pmt
           LEFT JOIN cte_2
           ON  pmt.payment_id=cte_2.payment_id
              and cte_2.purchase_number <= 3
    GROUP  BY pmt.customer_id
    ORDER  BY pmt.customer_id ASC
    

    CTE 只是为每笔付款分配付款编号,然后我们使用左联接通过付款 ID 将付款表连接到该 CTE,因为内部联接会删除付款编号 > 3 的付款(但我们想计算它们)

    【讨论】:

    • 非常感谢您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 2013-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多