sql根据列值查找与当前行关联的行

b4wnujal  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(322)

假设我有一个系统,用户可以根据活动获取令牌。对于任何令牌x,我想知道使用令牌x的用户获得了哪些其他令牌。
例如:

Table Tokens:
PrimaryKey = TokenID

TokenId | UserID | TokenName | TokenGiver
-----------------------------------------
    111 |      1 |    token_a|        bob
    222 |      1 |    token_b|        bob
    333 |      1 |    token_c|        bob
    444 |      2 |    token_a|        bob
    555 |      2 |    token_c|        bob
    666 |      3 |    token_b|        bob
    777 |      4 |    token_c|        bob
    888 |      5 |    token_d|        bob

预期输出,与此相近:

TokenName | count | AlsoEarned
------------------------------
  token_a |     2 | [token_b: 1, token_c: 2]
  token_b |     2 | [token_a: 1, token_c: 1]
  token_c |     3 | [token_a: 2, token_b: 1] 
  token_d |     1 | []

说明:对于令牌\u a,userid=1和userid=2都获得了它。userid=1还获得了token\u b和token\u c,userid=2还获得了token\u c。因此,对于令牌a,我们有[令牌b:1,令牌c:2]

6yt4nkrj

6yt4nkrj1#

您可以通过self-join获取基本数据

select t1.token_name, t2.token_name, count(*) as cnt
from tokens t1 join
     tokens t2
     on t1.user_id = t2.user_id and t1.token_name <> t2.token_name
group by t1.token_name, t2.token_name;

那么你似乎希望在这上面加一个聚合:

select token1, num_users, array_agg(tt) as also_earned
       from (select t1.token_name as token1, t2.token_name as token2, count(*) as cnt, t1.num_users
      from (select t1.*, count(distinct user_id) over (partition by token_name) as num_users
            from tokens t1
           ) t1 join
           tokens t2
           on t1.user_id = t2.user_id and t1.token_name <> t2.token_name
      group by t1.token_name, t2.token_name, t1.num_users
     ) tt
group by token1, num_users
mtb9vblg

mtb9vblg2#

下面是bigquery标准sql


# standardSQL

WITH temp AS (
  SELECT TokenName, UserID, COUNT(1) cnt 
  FROM `project.dataset.table`  
  GROUP BY TokenName, UserID
)
SELECT 
  TokenName, 
  ANY_VALUE(cnt) cnt,
  STRING_AGG(FORMAT('%s: %i', alsoTokenName, alsocnt), ', ') AlsoEarned
FROM (
  SELECT TokenName, SUM(cnt) AS cnt
  FROM temp
  GROUP BY TokenName
) 
LEFT JOIN (
  SELECT a.TokenName, b.TokenName AS alsoTokenName, SUM(b.cnt) AS alsocnt
  FROM temp a LEFT JOIN temp b USING (UserID)
  WHERE a.TokenName != b.TokenName
  GROUP BY TokenName, alsoTokenName
) 
USING(TokenName)
GROUP BY TokenName
-- ORDER BY TokenName

如果要应用于问题的样本数据,则输出为

Row TokenName   cnt     AlsoEarned   
1   token_a     2       token_b: 1, token_c: 2   
2   token_b     2       token_a: 1, token_c: 1   
3   token_c     3       token_a: 2, token_b: 1   
4   token_d     1       null

相关问题