簡體   English   中英

Google BigQuery SQL:獨立訂購兩列

[英]Google BigQuery SQL: Order two columns independently

假設我有一些數據,例如:

grp   v1   v2
---   --   --
 2    5    7
 2    4    9
 3    10   2
 3    11   1

我想創建獨立於表順序的新列-這樣兩列具有獨立的順序,即按v1而不是v2進行排序,同時按grp進行分區。

結果(獨立排序,由grp划分)為:

grp   v1   v2  v1_ordered v2_ordered
---   --   --  ---------- ----------
 2    5    7       4          7
 2    4    9       5          9
 3    10   2      10          1
 3    11   1      11          2

一種方法是創建兩個表和CROSS JOIN。 但是,我正在處理太多的數據行,以使其在計算上難以處理-是否可以在沒有JOIN的單個查詢中完成此操作?

基本上,我想這樣寫SQL:

SELECT
  *,
  v1 OVER (PARTITION BY grp ORDER BY v1 ASC) as v1_ordered,
  v2 OVER (PARTITION BY grp ORDER BY v2 ASC) as v2_ordered
FROM [example_table]

這打破了表行的含義,但這是許多應用程序所必需的功能-例如,計算兩個字段CORR(v1_ordered, v2_ordered).之間的有序相關性CORR(v1_ordered, v2_ordered).

這可能嗎?

我認為您的方向正確! 您只需要使用適當的窗口功能。 在這種情況下為Row_number()。 它應該工作!

根據@cgn請求添加工作示例:
我認為沒有辦法完全避免使用JOIN。
同時在以下示例中,在其他答案中僅使用ONE JOINTWO JOIN

SELECT 
  a.grp AS grp, 
  a.v1 AS v1, 
  a.v2 AS v2, 
  a.v1 AS v1_ordered, 
  b.v2 AS v2_ordered 
FROM (
  SELECT grp, v1, v2, ROW_NUMBER() OVER(PARTITION BY grp ORDER BY v1) AS v1_order
  FROM [example_table]
) AS a
JOIN (
  SELECT grp, v1, v2, ROW_NUMBER() OVER(PARTITION BY grp ORDER BY v2) AS v2_order
  FROM [example_table]
) AS b
ON a.grp = b.grp AND a.v1_order = b.v2_order 

結果符合預期:

grp v1  v2  v1_ordered  v2_ordered   
2    4   9           4           7   
2    5   7           5           9   
3   10   2          10           1   
3   11   1          11           2   

現在您可以如下使用CORR()

SELECT grp, CORR(v1_ordered, v2_ordered) AS [corr]
FROM (
  SELECT 
    a.grp AS grp, 
    a.v1 AS v1, 
    a.v2 AS v2, 
    a.v1 AS v1_ordered, 
    b.v2 AS v2_ordered 
  FROM (
    SELECT grp, v1, v2, ROW_NUMBER() OVER(PARTITION BY grp ORDER BY v1) AS v1_order
    FROM [example_table]
  ) AS a
  JOIN (
    SELECT grp, v1, v2, ROW_NUMBER() OVER(PARTITION BY grp ORDER BY v2) AS v2_order
    FROM [example_table]
  ) AS b
  ON a.grp = b.grp AND a.v1_order = b.v2_order
)
GROUP BY grp

這將為您工作。

SQLFiddle Demo in SQL Server

注意:示例中提到的順序對於從數據庫返回行是不必要的。 就我而言,對於v1 ,我得到4,5,10,11與您的5,4,10,11不同。 但是,您的輸出將與您想要的相同。

Select t.grp,t.v1,t.v2,
v1.v1 as v1_ordered,v2.v2 as v2_ordered
From
(
    select t1.*,
    row_number() over (partition by grp
                   Order by v1) v1o
    ,
    row_number() over (partition by grp
                   Order by v2) v2o
    from table1 t1
) t
Inner join
(
    Select t.*,
    row_number() over (partition by grp
                   Order by v1) v1o
    From table1 t
) v1
On t.grp=v1.grp
And t.v1o=v1.v1o
Inner join
(
    Select t.*,
    row_number() over (partition by grp
                   Order by v2) v2o
    From table1 t
) v2
On t.grp=v2.grp
And t.v1o=v2.v2o

輸出:

+------+-----+-----+-------------+------------+
| grp  | v1  | v2  | v1_ordered  | v2_ordered |
+------+-----+-----+-------------+------------+
|   2  |  4  |  9  |          4  |          7 |
|   2  |  5  |  7  |          5  |          9 |
|   3  | 10  |  2  |         10  |          1 |
|   3  | 11  |  1  |         11  |          2 |
+------+-----+-----+-------------+------------+

AI並非100%確信這可以在BigQuery中使用,但是可以這樣:

select e.*, ev1.v1, ev2.v2
from (select e.*,
             row_number() over (partition by grp order by v1) as seqnum_v1,
             row_number() over (partition by grp order by v2) as seqnum_v2
      from example e
     ) e join
     (select e.*, row_number() over (partition by grp order by v1) as seqnum_v1
      from example e
     ) ev1
     on ev1.grp = e.grp and ev1.seqnum_v1 = e.seqnum_v1 join
     (select e.*, row_number() over (partition by grp order by v2) as seqnum_v2
      from example e
     ) ev2
     on ev2.grp = e.grp and ev2.seqnum_v2 = e.seqnum_v2;

這個想法是給每個列分配一個獨立的順序。 然后聯接回到原始表以獲取實際值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM