首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Oracle (和MySQL)中是否有表示派生列列表的通用解决方案?

在Oracle (和MySQL)中是否有表示派生列列表的通用解决方案?
EN

Stack Overflow用户
提问于 2013-01-03 03:09:43
回答 3查看 2.4K关注 0票数 18

许多SQL数据库支持SQL标准所称的<derived column list>。这些数据库至少包括CUBRID、Derby、Firebird、HSQLDB、Postgres、SQL Server和Sybase SQL Anywhere。来自SQL:2008规范的(简化)摘录

代码语言:javascript
复制
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中,这是非常符合标准的)

代码语言:javascript
复制
-- 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 documentation,我不能使用<derived column list>规范重命名列。当然,我可以分别重命名表和列,如下所示:

代码语言:javascript
复制
-- 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这样的数据库上工作的解决方案。一个相关的问题:

How to select an unaliased numeric literal from a sub-select

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-01-08 05:24:54

对于MySQL解决方案,可以使用UNION设置零行查询条件中所有列的名称,然后查询更复杂的内容:

代码语言:javascript
复制
SELECT null AS a, null AS b, null AS c FROM dual WHERE false
UNION ALL
SELECT <expr>, <expr>, <expr>
FROM <realtable>...

只有UNION的第一个查询术语定义了整个查询的列名。后续查询条件中的列名(或缺少列名)不会影响最终的列名。

您确实需要知道列数,但是将两个查询项分开应该很容易。据我所知,它在Oracle和MySQL中都可以工作(但是,我只在MySQL中测试过它,没有在Oracle中测试它)。

票数 10
EN

Stack Overflow用户

发布于 2013-01-03 21:47:31

由于您必须知道列数,但不一定知道列名,因此可以根据需要使用WITH子句重命名这些列。例如(在Oracle和SQL Server中工作时,手边没有MySQL实例):

代码语言:javascript
复制
WITH t(x,y,z) as (select * from TABLE(fn_returning_xcols(3)))
select * from t;

在这里,我们不知道内部select中的列名,但我们可以在外部WITH子句中重命名它们。

在Oracle中使用PIVOT的另一个示例:

代码语言:javascript
复制
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;

同样,我们并不关心内部select列名是什么(内部枢轴创建了一些奇怪的列名),我们只需要知道有多少列,我们就可以重命名。

票数 9
EN

Stack Overflow用户

发布于 2013-01-04 02:13:11

正如用户tbone here所建议的那样,对于我的问题,公用表表达式是一个很好的解决方案,至少对Oracle来说是这样。为了完整起见,下面是我在Oracle中使用CTE编写的示例查询

代码语言:javascript
复制
-- 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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14127707

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档