SQL:Join上的级联条件

时间:2018-06-07 19:22:28

标签: sql google-bigquery

我在SO上发现了一些类似的问题,但没有什么适用于我的情况。

我在表1中有一个包含数亿行的大型数据集,我正在寻找运行以下查询的最有效方法。 我正在使用Google BigQuery,但我认为这是适用于任何DBMS的一般SQL问题?

我需要将所有者应用于表1中的每一行。我想加入以下优先级:

1:如果item_id与表2中的标识符匹配

2:如果没有item_id匹配item_name上的try match

3:如果没有item_id或item_name匹配item_division上的try match

4:如果没有item_division匹配,则返回null

表1 - 数据点

| id | item_id | item_name | item_division | units | revenue
|----|---------|-----------|---------------|-------|---------
| 1  |   xyz   |  pen      |      UK       |   10  |   100
| 2  |   pqr   |  cat      |      US       |   15  |   120
| 3  |   asd   |  dog      |      US       |   12  |   105
| 4  |   xcv   |  hat      |      UK       |   11  |   140
| 5  |   bnm   |  cow      |      UK       |   14  |   150

表2 - 标识符:

| id |  type   |  code     | owner | 
|----|---------|-----------|-------|
| 1  |   id    |  xyz      |  bob  |  
| 2  |   name  |  cat      |  dave |    
| 3  | division|  UK       | alice |    
| 4  |   name  |  pen      | erica |      
| 5  |   id    |  xcv      | fred  |  

期望的输出:

| id | item_id | item_name | item_division | units | revenue | owner |
|----|---------|-----------|---------------|-------|---------|-------|
| 1  |   xyz   |  pen      |      UK       |   10  |   100   |  bob  | <- id
| 2  |   pqr   |  cat      |      US       |   15  |   120   |  dave | <- code
| 3  |   asd   |  dog      |      US       |   12  |   105   |  null | <- none
| 4  |   xcv   |  hat      |      UK       |   11  |   140   |  fred | <- id
| 5  |   bnm   |  cow      |      UK       |   14  |   150   | alice | <- division

到目前为止,我的尝试涉及到多个人加入桌面,我担心它会变得非常低效。

任何帮助都非常感激。

3 个答案:

答案 0 :(得分:0)

我正在使用以下查询(感谢@Barmar),但想知道Google BigQuery中是否有更有效的方法:

SELECT a.*, COALESCE(b.owner,c.owner,d.owner) owner FROM datapoints a
LEFT JOIN identifiers b on a.item_id = b.code and b.type = 'id'
LEFT JOIN identifiers c on a.item_name = c.code and c.type = 'name'
LEFT JOIN identifiers d on a.item_division = d.code and d.type = 'division'

答案 1 :(得分:0)

我不确定BigQuery今天是否优化了这样的查询 - 但至少你会编写一个查询,提供强大的提示,以便在不需要时运行子查询:

#standardSQL
SELECT COALESCE(
  null
  , (SELECT MIN(payload) 
     FROM `githubarchive.year.2016` 
     WHERE actor.login=a.user)
  , (SELECT MIN(payload) 
     FROM `githubarchive.year.2016` 
     WHERE actor.id = SAFE_CAST(user AS INT64))
)
FROM (SELECT '15229281' user) a


4.2s elapsed, 683 GB processed
{"action":"started"}    

例如,以下查询需要很长时间才能运行,但BigQuery可以在将来大量优化其执行(取决于用户需要像这样的操作的频率):

#standardSQL
SELECT COALESCE(
  "hello"
  , (SELECT MIN(payload) 
     FROM `githubarchive.year.2016` 
     WHERE actor.login=a.user)
  , (SELECT MIN(payload) 
     FROM `githubarchive.year.2016` 
     WHERE actor.id = SAFE_CAST(user AS INT64))
)
FROM (SELECT actor.login user FROM `githubarchive.year.2016` LIMIT 10) a


114.7s elapsed, 683 GB processed
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello

答案 2 :(得分:0)

BigQuery Standard SQL的另一个选项

    
#standardSQL
SELECT ARRAY_AGG(a)[OFFSET(0)].*, 
  ARRAY_AGG(owner 
    ORDER BY CASE 
      WHEN type = 'id' THEN 1
      WHEN type = 'name' THEN 2
      WHEN type = 'division' THEN 3
    END  
    LIMIT 1
  )[OFFSET(0)] owner
FROM Datapoints a
JOIN Identifiers b
  ON (a.item_id = b.code AND b.type = 'id')
   OR (a.item_name = b.code AND b.type = 'name')
   OR (a.item_division = b.code AND b.type = 'division')
GROUP BY a.id
ORDER BY a.id  

它省略了k =没有所有者的条目 - 如下面的结果(id = 3因为没有所有者而被淘汰)

Row id  item_id item_name   item_division   units   revenue owner    
1   1   xyz     pen         UK              10      100     bob  
2   2   pqr     cat         US              15      120     dave     
3   4   xcv     hat         UK              11      140     fred     
4   5   bnm     cow         UK              14      150     alice