Sql 列别名引用
这个查询将数字分解为它所尊重的位置,如千、百、五十等等。问题是我无法通过别名来引用该列。在Oracle中,我遇到以下错误: ora-00904:“两个”:无效标识符 但该代码在MS Access中运行良好 查询:Sql 列别名引用,sql,oracle,ora-00904,Sql,Oracle,Ora 00904,这个查询将数字分解为它所尊重的位置,如千、百、五十等等。问题是我无法通过别名来引用该列。在Oracle中,我遇到以下错误: ora-00904:“两个”:无效标识符 但该代码在MS Access中运行良好 查询: SELECT BT, CNO, AMT, TRUNC(AMT/1000) AS THS, TRUNC((AMT-(THS*1000))/500) AS FIVHUN, TRUNC((AMT-((THS*1000)+(FIVH
SELECT
BT,
CNO,
AMT,
TRUNC(AMT/1000) AS THS,
TRUNC((AMT-(THS*1000))/500) AS FIVHUN,
TRUNC((AMT-((THS*1000)+(FIVHUN*500)))/100) AS HUND,
TRUNC((AMT-(((THS*1000)+(FIVHUN*500))+(HUND*100)))/50) AS FIF,
TRUNC((AMT-(((THS*1000)+(FIVHUN*500))+(HUND*100)+(FIF*50)))/20) AS TWENTY,
TRUNC((AMT-(((THS*1000)+(FIVHUN*500))+(HUND*100)+(FIF*50)+(TWENTY*20)))/10) AS TENS,
TRUNC((AMT-(((THS*1000)+(FIVHUN*500))+(HUND*100)+(FIF*50)+(TWENTY*20)+(TENS*10)))/5) AS FIVES,
TRUNC((AMT-(((THS*1000)+(FIVHUN*500))+(HUND*100)+(FIF*50)+(TWENTY*20)+(TENS*10)+(FIVES*5)))/2) AS TWOS,
TRUNC((AMT-(((THS*1000)+(FIVHUN*500))+(HUND*100)+(FIF*50)+(TWENTY*20)+(TENS*10)+(FIVES*5)+(TWOS*2)))/1) AS ONES
FROM
EMPLOYER;
您只能在外部选择中引用列别名,因此除非重新计算每个列的所有先前值,否则需要嵌套每个级别,这有点难看:
select bt, cno, amt, ths, fivhun, hund, fif, twenty, tens, fives, twos,
trunc((amt-(ths*1000)-(fivhun*500)-(hund*100)-(fif*50)-(twenty*20)
-(tens*10)-(fives*5)-(twos*2))/1) as ones
from (
select bt, cno, amt, ths, fivhun, hund, fif, twenty, tens, fives,
trunc((amt-(ths*1000)-(fivhun*500)-(hund*100)-(fif*50)-(twenty*20)
-(tens*10)-(fives*5))/2) as twos
from (
select bt, cno, amt, ths, fivhun, hund, fif, twenty, tens,
trunc((amt-(ths*1000)-(fivhun*500)-(hund*100)-(fif*50)-(twenty*20)
-(tens*10))/5) as fives
from (
select bt, cno, amt, ths, fivhun, hund, fif, twenty,
trunc((amt-(ths*1000)-(fivhun*500)-(hund*100)-(fif*50)
-(twenty*20))/10) as tens
from (
select bt, cno, amt, ths, fivhun, hund, fif,
trunc((amt-(ths*1000)-(fivhun*500)-(hund*100)
-(fif*50))/20) as twenty
from (
select bt, cno, amt, ths, fivhun, hund,
trunc((amt-(ths*1000)-(fivhun*500)
-(hund*100))/50) as fif
from (
select bt, cno, amt, ths, fivhun,
trunc((amt-(ths*1000)-(fivhun*500))/100) as hund
from (
select bt, cno, amt, ths,
trunc((amt-trunc(ths*1000))/500) as fivhun
from (
select bt, cno, amt,
trunc(amt/1000) as ths from employer
)
)
)
)
)
)
)
);
。。。它给出了类似于:
BT CNO AMT THS FIVHUN HUND FIF TWENTY TENS FIVES TWOS ONES
--- --- ---------------- ------- ------ ---- --- ------ ---- ----- ---- ----
1 2 123,456,789 123456 1 2 1 1 1 1 2 0
3 4 87,654,321 87654 0 3 0 1 0 0 0 1
5 6 1,234,567 1234 1 0 1 0 1 1 1 0
不是那么漂亮,而是一个递归版本,主要是为了我自己的娱乐:
with t as (
select bt, cno, amt, x,
case x when 1 then 1000 when 2 then 500 when 3 then 100
when 4 then 50 when 5 then 20 when 6 then 10 when 7 then 5
when 8 then 2 when 9 then 1 end as bill
from employer
cross join (select level as x from dual connect by level < 10)
),
r (bt, cno, amt, x, y, running) as (
select t.bt, t.cno, t.amt, 0 as x, 0 as y, 0 as running
from t
where t.x = 1 -- could be any x, just want one row per bt/cno
union all
select t.bt, t.cno, t.amt, t.x,
trunc((t.amt - r.running)/t.bill) as y,
r.running + (t.bill * trunc((t.amt - r.running)/t.bill)) as running
from t
join r on r.bt = t.bt and r.cno = t.cno and r.x = t.x - 1
)
select bt, cno, amt,
max(case when x = 1 then y else 0 end) as ths,
max(case when x = 2 then y else 0 end) as fivhun,
max(case when x = 3 then y else 0 end) as hund,
max(case when x = 4 then y else 0 end) as fif,
max(case when x = 5 then y else 0 end) as twenty,
max(case when x = 6 then y else 0 end) as tens,
max(case when x = 7 then y else 0 end) as fives,
max(case when x = 8 then y else 0 end) as twos,
max(case when x = 9 then y else 0 end) as ones
from r
group by bt, cno, amt
order by bt, cno;
顺便说一句,我最初试图用
mod()
(正如AndriyM所建议的)来简化这个过程,但是你不能独立地计算每个值:
select bt, cno, amt,
floor( amt/1000) as ths,
floor(mod(amt, 1000)/ 500) as fivhun,
floor(mod(amt, 500)/ 100) as hund,
floor(mod(amt, 100)/ 50) as fif,
floor(mod(amt, 50)/ 20) as twenty,
floor(mod(amt, 20)/ 10) as tens,
floor(mod(amt, 10)/ 5) as fives,
floor(mod(amt, 5)/ 2) as twos,
floor(mod(amt, 2)/ 1) as ones
from employer
order by bt, cno;
BT CNO AMT THS FIVHUN HUND FIF TWENTY TENS FIVES TWOS ONES
--- --- ---------------- ------- ------ ---- --- ------ ---- ----- ---- ----
1 2 123,456,789 123456 1 2 1 1 0 1 2 1
3 4 87,654,321 87654 0 3 0 1 0 0 0 1
5 6 1,234,567 1234 1 0 1 0 0 1 1 1
大多数值是相同的,但是
tens
都是0
,而的值都是1
。后者很容易解释,但更多的问题是为什么它们不都是1
。如果fives
值为1
,则要拆分的剩余金额将变为偶数,因此ones
必须为0
。类似地,tens
值没有考虑fif
。因此,这些值之间存在依赖关系,而这种简单的查询无法处理这些依赖关系。当然,您可以调整问题列以将其考虑在内,但要冒着引入细微错误的风险。如果您使用另一个别名呢?也许TWOS
是一个保留字,尽管我不知道。你不能在同一(级别)查询中使用别名。From:“您可以使用列别名c_alias来标记select列表中紧挨着前面的表达式,以便以新标题显示该列。该别名在查询期间有效地重命名select列表项。该别名可用于ORDER BY子句,但不能用于查询中的其他子句。”。这解释了错误,但并没有真正帮助您…您不能在同一SELECT子句中引用别名,但可以在group by/orderby中引用别名,因为别名是工作表中的列名,在选择过程中甚至没有形成。@Vikdor-您也不能在group by
中使用它(更麻烦的是,也不能使用它); 只有在《order by》
@AlexPoole》中,我没有意识到这一点,谢谢你指出。如果为自己的娱乐编写一个递归CTE不值得投票,我不知道是什么does@APC-我在这里真正受益的一件事是有一个借口去尝试我以前从未接触过的东西。我读过递归CTE,但从来没有理由使用它;类似地,在试图回答(或仅仅理解)一个从分析中获益的问题之前,我没有做过太多的分析工作。许多问题确实让我思考(并不总是成功)。所以这个网站对我来说至少是一个学习工具,就像它是一个帮助他人的地方一样,尽管还没有问过任何问题。这是我花这么多时间在这里的借口,无论如何…谢谢你告诉我我的DIV和MOD是多么的过于简单化。但愿我能不止一次投票。
select bt, cno, amt,
floor( amt/1000) as ths,
floor(mod(amt, 1000)/ 500) as fivhun,
floor(mod(amt, 500)/ 100) as hund,
floor(mod(amt, 100)/ 50) as fif,
floor(mod(amt, 50)/ 20) as twenty,
floor(mod(amt, 20)/ 10) as tens,
floor(mod(amt, 10)/ 5) as fives,
floor(mod(amt, 5)/ 2) as twos,
floor(mod(amt, 2)/ 1) as ones
from employer
order by bt, cno;
BT CNO AMT THS FIVHUN HUND FIF TWENTY TENS FIVES TWOS ONES
--- --- ---------------- ------- ------ ---- --- ------ ---- ----- ---- ----
1 2 123,456,789 123456 1 2 1 1 0 1 2 1
3 4 87,654,321 87654 0 3 0 1 0 0 0 1
5 6 1,234,567 1234 1 0 1 0 0 1 1 1