微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 group_by 将第一个创建的记录的标识符添加到 select 语句中

如何解决使用 group_by 将第一个创建的记录的标识符添加到 select 语句中

我有以下付款表

┌─name───────────────────────────┬─type────────────────────────────┐
│ payment_id                     │ UInt64                          │
│ factory                        │ String                          │
│ user_id                        │ UInt64                          │
│ amount_cents                   │ Int64                           │
│ action                         │ String                          │
│ success                        │ UInt8                           │
│ country                        │ FixedString(2)                  │
│ created_at                     │ DateTime                        │
│ finished_at                    │ Nullable(DateTime)              │
└────────────────────────────────┴─────────────────────────────────┘

使用样本数据

┌─factory───┬─────────finished_at─┬─payment_id─┬─country─┬─action──┬─amount_cents─┬─user_id───┬
│ 0_factory │ 2021-01-18 00:00:01 │          1 │ BY      │ payment │            1 │         1 │ 
│ 0_factory │ 2021-01-18 00:00:02 │          2 │ BY      │ payment │            1 │         1 │ 
│ 1_factory │ 2021-01-18 00:00:02 │          2 │ PL      │ win     │            4 │         1 │ 
│ 1_factory │ 2021-01-18 00:00:03 │          3 │ PL      │ win     │            7 │         1 │ 
│ 2_factory │ 2021-01-18 00:00:01 │          4 │ PL      │ win     │            7 │         1 │ 
│ 2_factory │ 2021-01-18 00:00:02 │          1 │ PL      │ payment │            7 │         1 │ 
│ 2_factory │ 2021-01-18 00:00:03 │          2 │ PL      │ win     │            7 │         1 │ 
│ 2_factory │ 2021-01-18 00:00:04 │          3 │ GR      │ win     │            2 │         1 │ 
└───────────┴─────────────────────┴────────────┴─────────┴─────────┴─────────┴────────────────┘

这是我现在所拥有的一个例子

SELECT
       factory,user_id,payment_id,action,created_at
    FROM payments_all
    WHERE (payments_all.action = 'payment') AND (payments_all.factory IN ('0_factory','1_factory','2_factory')) AND isNotNull(payments_all.created_at)
    GROUP BY
        factory,action
    HAVING (min(created_at) >= toDate('2019-01-01 00:00:00')) AND (min(created_at) < toDate('2021-10-01 00:00:00'))
    ORDER BY user_id

┌─factory───┬─user_id─┬─payment_id─┬─action──┬──────────created_at─┐
│ 1_factory │       1 │          1 │ payment │ 2021-02-04 09:00:00 │
│ 0_factory │       1 │          1 │ payment │ 2021-01-17 00:00:01 │
│ 0_factory │       1 │          2 │ payment │ 2021-01-17 00:00:06 │
└───────────┴─────────┴────────────┴─────────┴─────────────────────┘

我需要添加新列 first_payment

first_payment 取值为 1,如果操作是支付 && 它是用户的第一笔付款。否则取值为 0。

first_payment 应该在所有期间都检查 所以预期的结果是:

┌─factory───┬─────────finished_at─┬─payment_id─┬─country─┬─action──┬─amount_cents─┬─user_id───┬first_payment─┐
│ 0_factory │ 2021-01-18 00:00:01 │          1 │ BY      │ deposit │            1 │         1 │           1  │
│ 0_factory │ 2021-01-18 00:00:02 │          2 │ BY      │ deposit │            1 │         1 │           0  │ 
│ 1_factory │ 2021-01-18 00:00:02 │          2 │ PL      │ win     │            4 │         1 │           0  │
│ 1_factory │ 2021-01-18 00:00:03 │          3 │ PL      │ win     │            7 │         1 │           0  │
│ 2_factory │ 2021-01-18 00:00:01 │          4 │ PL      │ win     │            7 │         1 │           0  │
│ 2_factory │ 2021-01-18 00:00:02 │          1 │ PL      │ deposit │            7 │         1 │           1  │
│ 2_factory │ 2021-01-18 00:00:03 │          2 │ PL      │ win     │            7 │         1 │           0  │
│ 2_factory │ 2021-01-18 00:00:04 │          3 │ GR      │ win     │            2 │         1 │           0  │
└───────────┴─────────────────────┴────────────┴─────────┴─────────┴─────────┴────────────────┘

解决方法

正如我所看到的,第一笔付款的 payment_id 始终为 1。因此,我认为您可以使用 CASE WHEN payment_id=1 Then 1 ELSE 0 END AS first_payment。请检查下面的查询 =>

WITH CTE AS
(SELECT
       factory,user_id,payment_id,action,created_at
    FROM payments_all
    WHERE (payments_all.action = 'payment') AND (payments_all.factory IN ('0_factory','1_factory','2_factory')) AND isNotNull(payments_all.created_at)
    GROUP BY
        factory,action
    HAVING (min(created_at) >= toDate('2019-01-01 00:00:00')) AND (min(created_at) < toDate('2021-10-01 00:00:00'))
) T1  

SELECT *,CASE WHEN payment_id=1 Then 1
         ELSE 0 END AS first_payment 
FROM CTE  
ORDER BY T1.user_id

注意: 查询是在 SQL Server 中编写的。请检查并告诉我。

,

我找不到太多关于 ClickHouse 的信息,但它似乎不支持窗口函数。

您的示例输出似乎也与您的示例表完全相同,再加上一列,所以我不确定您 GROUP BY 的意图是什么。

所以,我会在子查询上使用 LEFT JOIN

SELECT
  payments_all.*,CASE WHEN user_summary.user_id IS NOT NULL THEN 1 ELSE 0 END AS first_payment
FROM
  payments_all
LEFT JOIN
(
  SELECT
    user_id,factory,MIN(created_at)  AS first_created_at
  FROM
    payments_all
  WHERE
    action = 'payment'
  GROUP BY
    user_id,factory
)
  AS user_summary
    ON  payments_all.user_id    = user_summary.user_id
    ON  payments_all.factory    = user_summary.factory
    AND payments_all.created_at = user_summary.first_created_at
WHERE
     (payments_all.factory    IN ('0_factory','2_factory'))
 AND (payments_all.created_at >= toDate('2019-01-01 00:00:00'))
 AND (payments_all.created_at <  toDate('2021-10-01 00:00:00'))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。