当两者都可能更改时,按公共用户 ID 或事务 ID 对所有行进行分组

Grouping all rows by common userid or transactionid when both may change

上下文是我们有一个 userid 和一个 transactionid,但由于客户端设置,有时 userid 会更改但 transactionid 保持不变(当两者应该保持不变时),有时 transactionid 会更改但 userid 不会't(所以我们不能只使用 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

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

我们首先找到分配给每个事务 ID (tid) 的用户 ID (uid)。有很多方法可以选择这个assignment,但是会使用最小的(minimum)userid:

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)

现在我们有了作业,我们可以将它们加入原来的 table:

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)

这可以使用 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
) 

这应该 return 正确的 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