18

多くのSQLデータベースは、SQL標準で呼ばれるものをサポートしています<derived column list>。このようなデータベースには、少なくともCUBRID、Derby、Firebird、HSQLDB、Postgres、SQL Server、およびSybaseSQLAnywhereが含まれます。SQL:2008仕様からの(簡略化された)抜粋

7.6 <table reference>

Format
<table reference> ::=
    <table or query name> [ [ AS ] <correlation name>
      [ <left paren> <derived column list> <right paren> ] ]
  | <derived table> [ AS ] <correlation name>
      [ <left paren> <derived column list> <right paren> ]

つまり、私はこれらのようなものを表現することができます(たとえば、かなり標準に準拠しているPostgresで)

-- Rename a <table or query name> to u(b)
with t(a) as (select 1)
select * from t as u(b)

-- Rename a <derived table> to u(b)
select * from (select 1) as u(b)

現在、Oracleのドキュメントによると、仕様を使用して列の名前を変更することはできません<derived column list>。もちろん、次のように、テーブルと列の名前を個別に変更することもできます。

-- Rename a <table or query name> to u(b)
with t(a) as (select 1 from dual)
select u.a b from t u;

-- Rename a <derived table> to u(b)
select u.a b from (select 1 a from dual) u;

ただし、これには、以前の構文よりも派生テーブル(実際の列名)に関する知識が必要です。また、名前が変更された列はORDER BY、プロジェクション自体を含む他の句ではなく、プロジェクションの後でのみ使用できます(たとえば、句内)。

Oracle(およびMySQL)で、SQL標準が提案する方法でテーブルと列の名前を変更するより一般的な方法はありますか?特に、これは、配列のネスト解除、ピボット/ピボット解除テーブルの名前変更、複雑なサブクエリのインライン化、テーブル関数からの結果の名前変更などに役立つ可能性があります。

注意:上記の例にあまり焦点を当てないでください。彼らは本当に問題を説明するためにここにいます。実際のクエリははるかに複雑なので、名前の変更を実装するための非常に一般的な方法を探していますu(b)

:MySQLのようなデータベースで動作するソリューションをまだ探しています。関連する質問:
副選択からエイリアスされていない数値リテラルを選択する方法

4

3 に答える 3

10

MySQLソリューションの場合、を使用UNIONしてゼロ行クエリ用語のすべての列の名前を設定し、その後、より複雑なクエリを実行できます。

SELECT null AS a, null AS b, null AS c FROM dual WHERE false
UNION ALL
SELECT <expr>, <expr>, <expr>
FROM <realtable>...

UNIONの最初のクエリ用語のみが、クエリ全体の列名を定義します。後続のクエリ用語の列名(またはその欠如)は、最終的な列名には影響しません。

列の数を知る必要はありますが、2つのクエリ用語を分離しておくのは非常に簡単です。私の知る限り、これはOracleとMySQLの両方で機能します(ただし、私はMySQLでのみテストし、Oracleではテストしていません)。

于 2013-01-07T21:24:53.717 に答える
9

列の数を知っている必要がありますが、必ずしも列名を知っている必要はないため、WITH句を使用して、必要に応じてこれらの列の名前を変更できます。たとえば(WITHはOracleとSQL Serverで機能しますが、MySQLインスタンスは手元にありません):

WITH t(x,y,z) as (select * from TABLE(fn_returning_xcols(3)))
select * from t;

ここでは、内側のselectの列名はわかりませんが、外側のWITH句で名前を変更できます。

OracleでPIVOTを使用する別の例:

WITH t(a,b,c,d,e) as 
(
 select * from 
 (
  select level as levl from dual connect by level <= 5
 )
 PIVOT(max(levl) as l for levl in (1,2,3,4,5))
)
select * from t;

繰り返しますが、内側の選択列名が何であるかは関係ありません(内側のピボットはやや奇妙な列名を作成します)。列の数を知る必要があり、名前を変更できます。

于 2013-01-03T13:47:31.470 に答える
0

ここでユーザーtboneが示唆しているように、少なくともOracleにとっては、一般的なテーブル式が私の問題の良い解決策です。完全を期すために、OracleでCTEを使用して記述されたクエリの例を次に示します。

-- Rename a <derived table> to u(b) with Oracle
with u(b) as (select 1 from dual) 
select u.b from u

-- Rename a <derived table> to u(b) with H2, which only knows recursive CTEs
-- Thanks to a comment by user a_horse_with_no_name
with recursive u(b) as (
  select 1
  union all
  select null where false
)
select u.b from u
于 2013-01-03T18:13:10.550 に答える