从SQL表创建键值对

时间:2018-01-18 22:05:48

标签: mysql google-bigquery

我最近遇到了一个问题,我在列中有许多网站的名称(重复),我必须找到以http和https存在的域名(例如:https://www.google.com和{ {3}})。我提出的问题是 -

`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)时间。任何想法我怎么能这样做?提前致谢。

3 个答案:

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

答案 1 :(得分:1)

这是一个有趣的问题;我只扔了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)这个任务。

答案 2 :(得分:0)

这样的事情怎么样?子查询之间没有那么多的相关性。

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,这似乎有问题。