簡體   English   中英

在 SQL/Python 中使用動態日期值透視雪花查詢

[英]Pivoting Snowflake query with dynamic date values in either SQL/Python

我在這個網站上搜索了很多關於這個的主題,但無法實現任何解決方案。 我正在使用雪花來提取數據,然后使用數據透視函數來轉置表格。 問題是我必須在樞軸函數中指定靜態字段。 在我的查詢中,我將日期范圍設為 90 天,因此不斷更改日期效率不會很高。 我正在使用雪花連接在 Jupyter 中提取數據,因此 python 是一個選項。

示例查詢(這有效):

select * from (
   select date, id, count(products) as prod_count 
   from table1 where date >= '2019-01-01' and date <= '2019-01-05' 
   group by 1, 2) d
pivot (
   max(prod_count) for date in ('2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04', '2019-01-05')) piv 

我試過在“for date in”部分傳遞一個選擇不同的日期查詢,但這不起作用。 我還嘗試創建單獨的數據框和 python 列表,其中包含所有日期並將它們傳遞進來,但這也不起作用。 我還在這個論壇上嘗試了各種其他解決方案,但他們似乎專注於 TSQL 或 SQL Server 語法,這在我的情況下不起作用(至少當我嘗試時..)任何幫助表示贊賞。

編輯:

要顯示輸入與預期輸出的示例:

輸入:

Date        ID  Products
2019-01-01  1   A
2019-01-01  1   B
2019-01-01  2   A
2019-01-02  1   A
2019-01-02  1   B
2019-01-02  1   C
2019-01-02  2   A
2019-01-02  2   B

當前(和預期的,但動態的日期)輸出:

ID  2019-01-01   2019-01-02
1   2            3
2   1            2

如果范圍是 90 天,您可以調整該函數,但我們可以做的是返回一個動態查詢,並將您的動態參數作為輸入:

import pandas as pd


def generate_sql_dates(start_date="2019-01-01", end_date="2019-01-05"):
"""Date Generator, takes in a start and end date"""
   date_arrays = pd.date_range(start_date, end_date,freq='D')

   pivot_dates = tuple([x.strftime("%Y-%m-%d") for x in date_arrays])

   return f"""select * from (
   select date, id, count(products) as prod_count 
   from table1 where date >= '{start_date}' and date <= '{end_date}'
   group by 1, 2) d
   pivot (
   max(prod_count) for date in {pivot_dates}) piv"""

運行此返回:

qry = generate_sql_dates('2019-03-05','2019-04-05')
print(qry)

輸出:

select * from (
   select date, id, count(products) as prod_count 
   from table1 where date >= '2019-03-05' and date <= '2019-04-05'
   group by 1, 2) d
   pivot (
   max(prod_count) for date in ('2019-03-05', '2019-03-06', '2019-03-07', '2019-03-08', '2019-03-09', '2019-03-10', '2019-03-11', '2019-03-12', '2019-03-13', '2019-03-14', '2019-03-15', '2019-03-16', '2019-03-17', '2019-03-18', '2019-03-19', '2019-03-20', '2019-03-21', '2019-03-22', '2019-03-23', '2019-03-24', '2019-03-25', '2019-03-26', '2019-03-27', '2019-03-28', '2019-03-29', '2019-03-30', '2019-03-31', '2019-04-01', '2019-04-02', '2019-04-03', '2019-04-04', '2019-04-05')) piv

現在,如果您的日期需要是動態的,即您每天運行並希望它以觸發器開始,您可以使用日期時間函數,就像 SQL 中的GETDATE()

start = (pd.to_datetime('today')).strftime('%Y-%m-%d')
end = (pd.to_datetime('today') + pd.DateOffset(days=90)).strftime('%Y-%m-%d')

然后您可以將它們傳遞給函數 - 或者將它們保留為默認值。

這對於評論來說太長了,但我對 Python 的了解不夠多,無法為您提供功能齊全的答案。 不過,我可以解釋構建動態樞軸的方法。

設置好結果后,使用工具從您將要旋轉並轉換為列名的列中獲取不同值的列表。 在這種情況下,這似乎是您的date列。 至於工具,SQL SELECT DISTINCT可以工作,但 Python 可以做同樣的事情。 一種或另一種方式,獲取值列表,用逗號分隔它們並在需要時將它們包裝在分隔符中(對於需要它的日期),然后將該逗號分隔的列表保存到字符串變量中。 這在 Python 中可能更容易完成,但我認為它也可以在 Snowflake 中完成 無論你更舒服。

接下來,您將使用該列名稱列表來構建另一個變量,該變量將包含您的查詢的其余部分。 IN子句中,您將把上面的變量附加到您的列列表中。

SET @queryText = 'select * from (
   select date, id, count(products) as prod_count 
   from table1 where date >= '2019-01-01' and date <= '2019-01-05' 
   group by 1, 2) d
pivot (
   max(prod_count) for date in (' + @listOfColumnValues + ')) piv '

最后,執行包含在@queryText的查詢。

我將在類似問題How to pivot on dynamic values in Snowflake 上保留此答案的最新版本。

我編寫了一個 Snowflake 存儲過程來獲取 Snowflake 內部的動態支點,3 個步驟:

  1. 詢問
  2. 調用存儲過程call pivot_prev_results()
  3. 查找結果select * from table(result_scan(last_query_id(-2)))

步驟:

create or replace procedure pivot_prev_results()
returns string
language javascript
execute as caller as
$$
  var cols_query = `
      select '\\'' 
        || listagg(distinct pivot_column, '\\',\\'') within group (order by pivot_column)
        || '\\'' 
      from table(result_scan(last_query_id(-1)))
  `;
  var stmt1 = snowflake.createStatement({sqlText: cols_query});
  var results1 = stmt1.execute();
  results1.next();
  var col_list = results1.getColumnValue(1);
  
  pivot_query = `
         select * 
         from (select * from table(result_scan(last_query_id(-2)))) 
         pivot(max(pivot_value) for pivot_column in (${col_list}))
     `
  var stmt2 = snowflake.createStatement({sqlText: pivot_query});
  stmt2.execute();
  return `select * from table(result_scan('${stmt2.getQueryId()}'));\n  select * from table(result_scan(last_query_id(-2)));`;
$$;

查看https://hoffa.medium.com/dynamic-pivots-in-sql-with-snowflake-c763933987c了解更多信息。

暫無
暫無

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

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