【问题标题】:Grouping all rows by common userid or transactionid when both may change当两者都可能更改时,按共同的用户 ID 或事务 ID 对所有行进行分组
【发布时间】:2015-12-15 15:43:48
【问题描述】:

上下文是我们有一个用户 ID 和一个事务 ID,但有时用户 ID 更改但事务 ID 保持不变(当两者都应该保持不变时),由于客户端设置,有时事务 ID 更改但用户 ID 没有(所以我们不能只使用 transactionid)。

所以我们想要得到一些可以用作实际 ID 的东西。新列(即实际 ID)仅用于对行进行分组,因此它可以是任意(唯一)值。顺序根本不重要。

例子:

| userid | transactionid |
|--------|---------------|
| A      |             1 |
| A      |             2 |
| A      |             3 |
| B      |             2 |
| B      |             2 |
| C      |             4 |
| D      |             5 |
| D      |             5 |
| D      |             6 |
| E      |             6 |
| E      |             7 |
| F      |             4 |

可能变成:

| userid | transactionid | actualid |
|--------|---------------|----------|
| A      | 1             | A        |
| A      | 2             | A        |
| A      | 3             | A        |
| B      | 2             | A        |
| B      | 2             | A        |
| C      | 4             | C        |
| D      | 5             | E        |
| D      | 5             | E        |
| D      | 6             | E        |
| E      | 6             | E        |
| E      | 7             | E        |
| F      | 4             | C        |

我们使用的是 Presto,所以有一些限制(没有临时表,聚合查询中没有 DISTINCT 等)

在 Python 中使用 for 循环的解决方案如下所示:http://nbviewer.ipython.org/urls/gist.githubusercontent.com/jamesmcm/2554d5d4498b5d46d42d/raw/587ff552c34027e85ee199d5d8e5cb192e5550d1/gistfile1.txt

但我们需要 Presto 的解决方案。

这最初是在 Gist 上写的:https://gist.github.com/jamesmcm/9b9a559eb9f69405c04a

如果您想要正确的表格格式。

【问题讨论】:

    标签: sql presto


    【解决方案1】:

    这可以使用 windows 函数而不是连接来完成,并且需要比 @David 建议的额外步骤。

    使用下面的例子

    uid | tid
     B  |  2
     B  |  3
     B  |  4
     A  |  3
     E  |  1
    

    有可能

    SELECT 
        *,
        MIN(minuid) OVER (PARTITION BY mintid order by 1) as final_id
    FROM(
        SELECT 
            tid,
            uid,
            MIN(uid) OVER (PARTITION BY tid order by 1) as minuid,
            MIN(tid) OVER (PARTITION BY uid order by 1) as mintid
        FROM
            log
    ) 
    

    这应该返回正确的ID

    uid | tid | minuid | mintid | final_id
     B  |  2  |   B    |   2    |   A
     B  |  3  |   A    |   2    |   A
     B  |  4  |   B    |   2    |   A
     A  |  3  |   A    |   3    |   A
     E  |  1  |   E    |   1    |   E
    

    【讨论】:

      【解决方案2】:

      我们首先找到分配给每个 transactionid (tid) 的用户 ID (uid)。有很多方法可以选择此分配,但将使用最小(最小)的用户 ID:

      SELECT tid, min(uid) xid
      FROM log
      GROUP BY tid
      

      这会导致以下分配:

       tid | xid 
      -----+-----
         1 | A   
         2 | A   
         3 | A   
         4 | C   
         5 | D   
         6 | D   
         7 | E   
      (7 rows)
      

      现在我们有了分配,我们可以将它们加入到原始表中:

      SELECT a.uid, a.tid, b.xid
      FROM log a
      JOIN (
        SELECT tid, min(uid) xid
        FROM log
        GROUP BY tid
      ) b
      ON (a.tid = b.tid)
      ORDER BY 1, 2;
      

      输出:

       uid | tid | xid 
      -----+-----+-----
       A   |   1 | A   
       A   |   2 | A   
       A   |   3 | A   
       B   |   2 | A   
       B   |   2 | A   
       C   |   4 | C   
       D   |   5 | D   
       D   |   5 | D   
       D   |   6 | D   
       E   |   6 | D   
       E   |   7 | E   
       F   |   4 | C   
      (12 rows)
      

      【讨论】:

      • 谢谢,这很好用!我不确定如果有很多递归(即在 uid 变化和 tid 变化之间交换)它会起作用,但幸运的是我们目前没有这个问题。
      • 我认为此解决方案在这种情况下有效,但并不完全正确,(我无法在此处添加表格,请参阅我的答案以获取此方法未完全有效的示例)
      猜你喜欢
      • 2016-07-06
      • 2018-07-16
      • 2022-12-16
      • 2021-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-12
      • 1970-01-01
      相关资源
      最近更新 更多