MS SQL Serverで実行されるSQLクエリがあり、grouping()
、rank()
およびrollup()
関数/キーワードが含まれています。クエリは以下のとおりです。
これをどのようにPostgreSQLに変換できますか?
select top 100
sum(ss_net_profit)/sum(ss_ext_sales_price) as gross_margin
,i_category
,i_class
,grouping(i_category)+grouping(i_class) as lochierarchy
,rank() over (partition by grouping(i_category)+grouping(i_class)
,case when grouping(i_class) = 0 then i_category end
order by sum(ss_net_profit)/sum(ss_ext_sales_price) asc
) as rank_within_parent
from
ssv_itemv_storev_IJGBAgg
where
d_year = 2001
and s_state in ('TN')
group by rollup(i_category,i_class)
order by
lochierarchy desc
,case when (grouping(i_category)+grouping(i_class) = 0) then i_category end
,rank_within_parent;
ROLLUP
はPostgres 9.5で実装されています。
Postgres 9.4以前の元の回答:
rollup()
group by rollup(i_category,i_class)
を使用すると、階層的なステップで集計されます。これはSQL ServerのISO SQL標準を拡張したもので、Postgresには実装されていません。 2つの項目の場合、標準SQLとPostgresで3つの手順が必要です。
group by i_category
_group by i_category, i_class
_grouping()
function はこの拡張機能に付属しており、特定の列が各行で集計されるかどうかを示します。ここでは、結果の合計とグループ合計を最初にソートするために使用されます。
rank()
は標準のウィンドウ関数です Postgresでも同じように機能しますが、上記の調整のために書き直す必要があります。
_top 100
_ は _FETCH FIRST 100 ROWS ONLY
_ in標準SQL に変換され、Postgresだけでなく、より短い _LIMIT 100
_ (_FETCH FIRST
_構文は、SQL Server for 2012+バージョンで機能します ypercubeのコメントを参照 )。この集計クエリで100行の後で切り取るのは少し奇妙です。
[〜#〜] cte [〜#〜] を使用して、以下の複数の集計で中間結果を再利用しています。 LIMIT
を除いて、すべてが基本的にSQL Serverでも機能するはずです。
_WITH cte AS (
SELECT sum(ss_net_profit) AS sum_profit
, sum(ss_ext_sales_price) AS sum_price
, i_category, i_class
FROM ssv_itemv_storev_IJGBAgg
WHERE d_year = 2001
AND s_state = 'TN'
GROUP BY i_category, i_class
)
SELECT sum(sum_profit)/sum(sum_price) AS gross_margin
, NULL AS i_category, NULL AS i_class
, 2 AS lochierarchy
, 1 AS rank_within_parent
FROM cte
UNION ALL
( -- parentheses required!
SELECT sum(sum_profit)/sum(sum_price) AS gross_margin
, i_category, NULL AS i_class
, 1 AS lochierarchy
, rank() OVER (ORDER BY sum(sum_profit)/sum(sum_price)) AS rank_within_parent
FROM cte
GROUP BY i_category
ORDER BY rank_within_parent, i_category -- last item = my addition to break ties
)
UNION ALL
(
SELECT sum_profit/sum_price AS gross_margin
, i_category, i_class
, 0 AS lochierarchy
, rank() OVER (PARTITION BY i_category
ORDER BY sum_profit/sum_price) AS rank_within_parent
FROM cte
ORDER BY i_category, rank_within_parent, i_class -- last item = my addition to break ties
)
LIMIT 100;
_
(未テスト。)