web-dev-qa-db-ja.com

別の結果列の式で結果列を再利用する方法

例:

SELECT
   (SELECT SUM(...) FROM ...) as turnover,
   (SELECT SUM(...) FROM ...) as cost,
   turnover - cost as profit

確かにこれは(少なくともPostgresでは)無効ですが、サブクエリを2回書き換えずにクエリで同じことを達成する方法は?

46
Wernight

そのようです:

SELECT
   turnover,
   cost,
   turnover - cost as profit
from (
   (SELECT SUM(...) FROM ...) as turnover,
   (SELECT SUM(...) FROM ...) as cost
   ) as partial_sums
42

次のようなクエリを再利用できます。

WITH 
  TURNOVER AS (
    SELECT SUM(...) FROM ...)
  ),
  COST AS(
    SELECT SUM(...) FROM ...
  )

SELECT *
FROM(
 SELECT
   TURNOVER.sum as SUM_TURNOVER
 FROM
 TURNOVER,COST
 WHERE ....
) AS a

これは次と同等です:

SELECT *
FROM(
 SELECT
   TURNOVER.sum as SUM_TURNOVER
 FROM
 (
   SELECT SUM(...) FROM ...)
 )AS TURNOVER,
 (
   SELECT SUM(...) FROM ...
 )AS COST
 WHERE ....
) AS a

ここで注意すべき点があります。最初の方法は読みやすく再利用可能ですが、2番目の方法はDBがより適切な計画を選択する可能性があるため、より高速になる可能性があります。

12

おそらく、ここに示されているように、sqlの「with」句が役立つ場合があります http://orafaq.com/node/1879 (Oracleだけでなく、Postgresなどの他のデータベースも同様に行います)。

6
andrers52

実際に私はこれについて多くの作業を行い、多くのレンガの壁にぶつかりましたが、最終的に答えを見つけました-より多くのハック-しかし、それは非常にうまく機能し、クエリの読み取りオーバーヘッドを90%削減しました...

したがって、相関クエリを何度も複製してサブクエリから複数の列を取得するのではなく、コンマで区切られたvarcharに返すすべての値を連結して、アプリケーションで再び展開します...

代わりに

select a,b,
(select x from bigcorrelatedsubquery) as x,
(select y from bigcorrelatedsubquery) as y,
(select z from bigcorrelatedsubquery) as z
from outertable

今やる

select a,b,
(select convert(varchar,x)+','+convert(varchar,x)+','+convert(varchar,x)+',' 
from bigcorrelatedsubquery) from bigcorrelatedquery) as xyz
from outertable
group by country

これで、必要な3つの相関「スカラー」値がすべて揃いましたが、相関サブクエリは3回ではなく1回実行するだけで済みました。

4
bhealy
SELECT turnover, cost, turnover - cost
FROM
(
SELECT
(SELECT ...) as turnover,
(SELECT ...) as cost
) as Temp
4
Eric.K.Yung

次のように動作すると思います:

SELECT turnover, cost, turnover-cost as profit FROM
   (SELECT 1 AS FAKE_KEY, SUM(a_field) AS TURNOVER FROM some_table) a
INNER JOIN
   (SELECT 1 AS FAKE_KEY, SUM(a_nother_field) AS COST FROM some_other_table) b
USING (FAKE_KEY);

動物でテストされていない-あなたが最初になります! :-)

共有してお楽しみください。

3
Bob Jarvis

クロス適用または外部適用を使用します。

SELECT
  Calc1.turnover,
  Calc2.cost,
  Calc3.profit
from
   cross apply ((SELECT SUM(...) as turnover FROM ...)) as Calc1
   cross apply ((SELECT SUM(...) as cost FROM ...)) as Calc2

   /*
     Note there is no from Clause in Calc 3 below.
     This is how you can "stack" formulas like in Excel.
     You can return any number of columns, not just one.
   */
   cross apply (select Calc1.turnover - Calc2.cost as profit) as Calc3
0
William Egge

これはかなり古いですが、私はこの問題に遭遇してこの投稿を見ましたが、与えられた答えを使用して問題を解決することができなかったので、最終的にこの解決策に到達しました:

クエリが次の場合:

SELECT
   (SELECT SUM(...) FROM ...) as turnover,
   (SELECT SUM(...) FROM ...) as cost,
   turnover - cost as profit

サブクエリに変換してから、次のようなフィールドを使用できます。

SELECT *,(myFields.turnover-myFields.cost) as profit 
FROM
(      
SELECT
       (SELECT SUM(...) FROM ...) as turnover,
       (SELECT SUM(...) FROM ...) as cost

) as myFields

これが物事を行うのに悪い方法であるかどうかは完全にはわかりませんが、パフォーマンスに関しては、224,000レコードは、DBによる同じサブクエリの2倍になっているかどうかが不明で、1.5秒かかりました。

0
Niklas