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

时间:2015-09-18 13:11:59

标签: sql presto

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

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

我们首先找到分配给每个transactionid(tid)的用户标识(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)