簡體   English   中英

標准 SQL:將顯式交叉連接重寫為 WITH 子句

[英]Standard SQL: rewrite an explicit cross join to WITH clause

考慮一個具有兩個 JSONB 字段outputsinputs的表transactions 問題是如何使用 WITH 子句重寫此查詢?

-- Note: This query will process 111.85 MB when run.
SELECT
    transactions.hash AS CREATED_TX_HASH,
    transactions.block_number AS CREATED_BLOCK_ID,
    transactions.block_timestamp AS CREATED_BLOCK_TIME,
    outputs.index AS CREATED_INDEX,
    outputs.value / 1e8 AS OUTPUT_VALUE_BTC,
    transactions.hash AS SPENT_CREATED_TX_HASH,
    transactions.block_number AS SPENDING_BLOCK_ID,
    transactions.block_timestamp AS SPENDING_BLOCK_TIME,
    inputs.index AS SPENT_CREATED_INDEX,
    inputs.spent_transaction_hash as SPENDING_TX_HASH,
    inputs.spent_output_index AS SPENDING_INDEX,
    inputs.value / 1e8 AS INPUT_VALUE_BTC
FROM `bigquery-public-data.crypto_bitcoin.transactions` as transactions
CROSS JOIN
    transactions.outputs as outputs
CROSS JOIN
    transactions.inputs as inputs
-- FROM `bigquery-public-data.crypto_bitcoin.transactions` as transactions,
--     transactions.outputs as outputs,
--     transactions.inputs as inputs   
WHERE transactions.block_timestamp_month < '2009-02-01' 
ORDER BY 3

我需要的是創建 CTE 以保留臨時結果集,如下所示:

WITH outputs AS (
  SELECT
      transactions.hash AS CREATED_TX_HASH,
      transactions.block_number AS CREATED_BLOCK_ID,
      transactions.block_timestamp AS CREATED_BLOCK_TIME,
      outputs.index AS CREATED_INDEX,
      outputs.value / 1e8 AS OUTPUT_VALUE_BTC
  FROM `bigquery-public-data.crypto_bitcoin.transactions` as transactions,
      transactions.outputs as outputs
  WHERE transactions.block_timestamp_month < '2009-02-01'  

), inputs AS (

  SELECT
    transactions.hash AS SPENT_CREATED_TX_HASH,
    transactions.block_number AS SPENDING_BLOCK_ID,
    transactions.block_timestamp AS SPENDING_BLOCK_TIME,
    inputs.index AS SPENT_CREATED_INDEX,
    inputs.spent_transaction_hash as SPENDING_TX_HASH,
    inputs.spent_output_index AS SPENDING_INDEX,
    inputs.value / 1e8 AS INPUT_VALUE_BTC
  FROM `bigquery-public-data.crypto_bitcoin.transactions` as transactions,
      transactions.inputs as inputs
  WHERE transactions.block_timestamp_month < '2009-02-01'
)

但我不知道這兩個 CTE 上的哪個SELECT語句產生與上面的原始查詢相同的結果。

您需要通過CREATED_BLOCK_IDSPENDING_BLOCK_ID加入它們,此外,我使用ROW_NUMBER語句來避免重復值。

下面的查詢應該適合你:

    WITH outputs AS (
  SELECT
      transactions.hash AS CREATED_TX_HASH,
      transactions.block_number AS CREATED_BLOCK_ID,
      transactions.block_timestamp AS CREATED_BLOCK_TIME,
      outputs.index AS CREATED_INDEX,
      outputs.value / 1e8 AS OUTPUT_VALUE_BTC
  FROM `bigquery-public-data.crypto_bitcoin.transactions` as transactions,
      transactions.outputs as outputs
  WHERE transactions.block_timestamp_month < '2009-02-01'  

), inputs AS (

  SELECT
    transactions.hash AS SPENT_CREATED_TX_HASH,
    transactions.block_number AS SPENDING_BLOCK_ID,
    transactions.block_timestamp AS SPENDING_BLOCK_TIME,
    inputs.index AS SPENT_CREATED_INDEX,
    inputs.spent_transaction_hash as SPENDING_TX_HASH,
    inputs.spent_output_index AS SPENDING_INDEX,
    inputs.value / 1e8 AS INPUT_VALUE_BTC
  FROM `bigquery-public-data.crypto_bitcoin.transactions` as transactions,
      transactions.inputs as inputs
  WHERE transactions.block_timestamp_month < '2009-02-01'
)
SELECT * from 
(
  SELECT * , 
  ROW_NUMBER() OVER(PARTITION BY CREATED_BLOCK_ID, CREATED_INDEX, SPENDING_BLOCK_ID, SPENT_CREATED_INDEX, CREATED_TX_HASH, SPENT_CREATED_TX_HASH
                    ORDER BY CREATED_BLOCK_TIME DESC) as last
   from outputs o join inputs i 
on  o.CREATED_BLOCK_ID=SPENDING_BLOCK_ID 
order by o.CREATED_BLOCK_ID, o.CREATED_BLOCK_TIME, o.CREATED_INDEX, o.CREATED_TX_HASH  
)
WHERE last = 1 AND CREATED_TX_HASH = SPENT_CREATED_TX_HASH

output 看起來像:

在此處輸入圖像描述

最后,我建議您使用CROSS JOIN查詢,因為這個 function 比使用WITH子句的子查詢具有更好的性能。

暫無
暫無

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

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