【问题标题】:Creating key-value pairs from SQL table从 SQL 表创建键值对
【发布时间】:2018-01-18 22:05:48
【问题描述】:

我最近遇到了一个问题,我在一个列中有许多网站的名称(有重复),我必须找出同时作为 http 和 https 存在的域(例如:https://www.google.comhttp://www.google.com )。我的查询是 -

`SELECT distinct SPLIT(origin,"://")[OFFSET(1)] as domain 
   FROM "chrome-ux-report.chrome_ux_report.201710" x
     WHERE SPLIT(x.origin,"://")[OFFSET(0)] = "http"
     and  SPLIT(x.origin,"://")[OFFSET(1)] in  
      (SELECT  SPLIT(y.origin,"://")[OFFSET(1)] 
          FROM "chrome-ux-report.chrome_ux_report.201710" y 
            WHERE SPLIT(y.origin,"://")[OFFSET(0)] = "https" ) 
 ORDER BY domain`

此查询需要 O(n^2) 时间。了解了 python,我不禁想到了一个解决方案,我可以构建一个以域为键、http 和 https 存在为值的新表,例如 dict['www.google.com'] = [1,1 ] 或在 sql 中 -

                Domain     http     https
        www.google.com      1         1

这需要 O(n) 时间。知道我该怎么做吗?提前致谢。

【问题讨论】:

  • 问题是找到所有以 https 和 http 形式存在的域。我从 python 中获取了字典的想法。 (现在我看到它是多余的)
  • 您使用的是 MySQL 还是 BigQuery?你已经同时标记了这两者..

标签: mysql google-bigquery


【解决方案1】:

使用公用表表达式预先选择数据应该会减少很多 O(n^2)。不是 O(n),而是更接近。

WITH cte AS (
    SELECT DISTINCT origin
    FROM "chrome-ux-report.chrome_ux_report.201710" x
    WHERE SPLIT(x.origin,"://")[OFFSET(0)] IN ("http", "https")
)
SELECT DISTINCT SPLIT(origin,"://")[OFFSET(1)] AS domain
FROM cte
WHERE SPLIT(cte.origin,"://")[OFFSET(0)] = "http"
AND SPLIT(cte.origin,"://")[OFFSET(1)] IN (
    SELECT SPLIT(cte2.origin,"://")[OFFSET(1)]
    FROM cte AS cte2
    WHERE SPLIT(cte2.origin,"://")[OFFSET(0)] = "https"
)
ORDER BY domain

【讨论】:

    【解决方案2】:

    嗯,这是一个有趣的问题;我只会扔掉我的 2 美分。以下是我在 BigQuery 中解决此问题的方法:

    WITH data AS(
      SELECT 'http://google.com.br' AS origin UNION ALL
      SELECT 'https://google.com.br' AS origin UNION ALL
      SELECT 'https://www.google.com.br' UNION ALL
      SELECT 'http://domain1' UNION ALL
      SELECT 'https://domain2'
    )
    
    SELECT
      REGEXP_EXTRACT(origin, r'://(.*)') AS domain,
      MAX(IF(REGEXP_CONTAINS(origin, r'^http[^s]'), TRUE, FALSE)) http,
      MAX(IF(REGEXP_CONTAINS(origin, r'^https'), TRUE, FALSE)) https
    FROM data
    GROUP BY 1
    

    结果:

    Row domain              http    https    
    1   www.google.com.br   false   true     
    2   domain2             false   true     
    3   google.com.br       true    true     
    4   domain1             true    false
    

    我认为这个查询的 BigO 低于n^2,但它可能大于n:在 MySQL 中,一个索引列 AFAIK 可以在log(n) 中进行行查找(假设 b-index 树),就像这样在此查询中发生n 次,因此最终结果为nlog(n)

    (也许可以使用哈希映射到达O(n),但我不知道最终结果是否会是n

    另一方面,BigQuery 没有索引;正如您在post 中看到的那样,它确实有不同的数据管理策略(令人惊叹的阅读)。

    不过,我想 BigQuery 可能无法联系到 O(n) 来完成这项任务。

    【讨论】:

    • 你的查询输出了只存在http版本的域。(在o/p表中,http列全部为真,https列全部为假)
    • 奇怪...不知道为什么会这样。我模拟的数据似乎也和你一样。如果您使用模拟数据运行此查询,您会得到正确的结果吗?
    【解决方案3】:

    这样的事情呢?以这种方式,子查询之间几乎没有那么大的相关性。

    Select  sum(if(origin like 'http://%', 1,0 ) as http, 
    sum(if(origin like 'https://%', 1,0 ) as https,
    Replace(Replace (origin,'http://',''),'https://','') as domain
    Group by domain
    

    假设您确实需要 MySQL,这似乎值得怀疑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-27
      • 2021-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多