【问题标题】:SQL - Create an array based on the values of two other columnsSQL - 根据其他两列的值创建一个数组
【发布时间】:2020-07-04 16:29:20
【问题描述】:

我有以下数据:

-----------------------------------------
| client_id | link_hash_a | link_hash_b |
-----------------------------------------
|     1     |     abc     |     xyz     |
|     2     |     def     |     xyz     |
|     3     |     def     |     uvw     |
-----------------------------------------

我想使用 SQL 创建一个 client_id 数组,该数组与来自列 link_hash_alink_hash_b 的两个哈希值链接。

在当前情况下,结果将是一个值为 {1,2,3} 的唯一数组,因为客户端 1 和 2 与 link_hash_b 列的值 xyz 链接,客户端 2 和 3 与link_hash_a 列的值 def

有没有办法通过 SQL 查询来做到这一点?非常感谢您的意见。

【问题讨论】:

  • 您使用的是哪种 DBMS 产品? “SQL”只是一种查询语言,而不是特定数据库产品的名称(而且只有极少数产品真正支持数组)。请为您使用的数据库产品添加tagWhy should I tag my DBMS
  • 我正在使用 ClickHouse DBMS。它有一个标准的 SQL 语言,也可以处理数组。问题更多是关于使用数据来满足这一需求的方式/策略。由于 PostgreSQL 也适用于数组,如果你有使用 PGSQL 的答案,我会很高兴地接受它;)
  • 不清楚客户端 2 连接到客户端 1 和 3 是否重要(通过哈希 a 连接到客户端 1,通过哈希 b 连接到客户端 3)。如果是,这似乎是一些遍历问题(您将需要递归查询,它可以用 PG 解决,不能告诉 Clickhouse)。如果没有,基于两个 group bys(通过任一哈希列)的简单 SQL 就足够了。
  • 我首先尝试使用两个group by 查询,然后在查询中使用join 将它们的结果放在一个数组中,但我无法拥有完美的@987654334 数组@。我想我已经接近了,但那还不是。
  • 要回答你的问题@TomášZáluský,客户端 2 非常重要,因为事实上他与客户端 3 共享相同的哈希值和哈希值 b,他允许在客户端 1 和客户端 3 之间创建链接。

标签: sql arrays clickhouse


【解决方案1】:

也可以这样使用:

SELECT groupUniqArrayArray(client_ids) client_ids
FROM (
  SELECT link_hash, groupArray(client_id) client_ids
  FROM (
    SELECT DISTINCT client_id, arrayJoin([link_hash_a, link_hash_b]) as link_hash
    FROM (
      /* test data */
      SELECT data.1 client_id, data.2 link_hash_a, data.3 link_hash_b
      FROM (
        SELECT arrayJoin([
          (1, 'abc', 'xyz'),
          (2, 'def', 'xyz'),
          (3, 'def', 'uvw')]) data)))
  GROUP BY link_hash
  HAVING count() = 2)
/* result
┌─client_ids─┐
│ [2,1,3]    │
└────────────┘
*/

【讨论】:

    【解决方案2】:

    我想我找到了解决办法。我使用了另一列,即客户所属的club_id。在这种情况下,客户端 1、2 和 3 都是 club_id 1 的一部分。

    这是我使用 ClickHouse SQL 的代码,并考虑到input_table 是问题中显示的数据表:

    SELECT club_id, arrayConcat( clt_a, clt_b ) as tot_clt_arr, arrayUniq( arrayConcat( clt_a, clt_b ) ) as tot_clt
    FROM
    (
        SELECT club_id, clt_a
        FROM
            (
            SELECT club_id, link_hash_a, groupUniqArray(client_id) as clt_a
            FROM input_table
            GROUP BY club_id, link_hash_a
            )
        WHERE length(clt_a) >= 2
    ) JOIN
    (
        SELECT club_id, clt_b
        FROM
            (
            SELECT club_id, link_hash_b, groupUniqArray(client_id) as clt_b
            FROM input_table
            GROUP BY club_id, link_hash_b
            )
        WHERE length(clt_b) >= 2
    )
    USING club_id
    GROUP BY club_id, tot_clt_arr;
    
    

    它返回client_id 的数组以及tot_clt 列中唯一client_id 的数量。

    感谢@TomášZáluský 的帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-05
      • 2022-07-05
      • 2021-03-19
      • 2020-08-18
      • 2021-10-15
      • 1970-01-01
      相关资源
      最近更新 更多