Reputation: 580
select (select count(*) from tbl_account) as processed,
(select count(*) from tbl_rejected_account) as rejected,
processed -rejected as approved from tbl_control .
how can i get that 'approved' count without having to write two subqueries and subtract them later.
EDIT:
The original Query that i want to change:-
select
ACTIVITY_DATE
,SYSTEM_NAME
,START_TIME
,END_TIME
,INSTANCE_NO as instance_number
,case status when '1' then 'Success'
when '2' then 'In process'
when '3' then 'Failed' end as status
,(select count(distinct account_number) from tbl_account_detail where coretype=a.system_name and INSTANCE_NO=a.instance_no and a.activity_date=to_char(upload_date,'dd-MON-yy'))+
(select count(distinct account_number) from tbl_account_detail_exception where system_name=a.system_name and INSTANCE_NO=a.instance_no and a.activity_date=to_char(upload_date,'dd-MON-yy'))
as AccountCount
,(select count(distinct account_number) from tbl_account_detail where CREATOR='SYSTEM' and APPROVER='SYSTEM' and system_name=a.system_name and INSTANCE_NO=a.instance_no and a.activity_date=to_char(upload_date,'dd-MON-yy'))
as AutoApprovedCount
,(select count(distinct account_number) from tbl_account_detail where coretype=a.system_name and INSTANCE_NO=a.instance_no and a.activity_date=to_char(upload_date,'dd-MON-yy')) +
(select count(distinct account_number) from tbl_account_detail_exception where system_name=a.system_name and INSTANCE_NO=a.instance_no and
a.activity_date=to_char(upload_date,'dd-MON-yy')) -
(select count(distinct account_number) from tbl_account_detail where a.activity_date=to_char(upload_date,'dd-MON-yy') and CREATOR='SYSTEM' and APPROVER='SYSTEM' and system_name=a.system_name and INSTANCE_NO=a.instance_no)
as MaintenanceCount
from tbl_control_file_status a where activity_type='MAIN' and activity_name='START';
clearly this is not what should be the proper way,kindly provide an alternative solution.
Upvotes: 2
Views: 7300
Reputation: 238086
You can use a subquery to introduce aliases for use in the outer query:
select SubQueryAlias.*
, processed - rejected as approved
from (
select (
select count(*)
from tbl_account
) as processed,
(
select count(*)
from tbl_rejected_account
) as rejected
from dual
) as SubQueryAlias
;
It's often more readable to use a common-table expression (CTE) as in Alex Poole's answer.
Upvotes: 2
Reputation: 191275
You can't refer to a column alias in the same level of query it is defined, except in an order by
clause. That is because of the way the query is processed and the result set constructed, but also avoids ambiguity. This is mentioned in the documentatin:
Specify an alias for the column expression. Oracle Database will use this alias in the column heading of the result set. The AS keyword is optional. The alias effectively renames the select list item for the duration of the query. The alias can be used in the order_by_clause but not other clauses in the query.
You could use a CTE for each subquery, or inline views:
select ta.processed, tra.rejected, ta.processed - tra.rejected as approved
from (
select count(*) as processed from tbl_account
) ta
cross join (
select count(*) as rejected from tbl_rejected_account
) tra
Or if you really have a correlation with the third table:
select tc.id, ta.processed, tra.rejected, ta.processed - tra.rejected as approved
from tbl_control tc
join (
select id, count(*) as processed from tbl_account group by id
) ta on ta.id = tc.id
join (
select id, count(*) as rejected from tbl_rejected_account group by id
) tra on tra.id = tc.id
You haven't said what the relationship is so I've assumed a common ID column. Using CTEs rather than inline views that would look like:
with ta as (
select id, count(*) as processed from tbl_account group by id
), tra as (
select id, count(*) as rejected from tbl_rejected_account group by id
)
select tc.id, ta.processed, tra.rejected, ta.processed - tra.rejected as approved
from tbl_control tc
join ta on ta.id = tc.id
join tra on tra.id = tc.id
You may need outer joins and nvl if either subquery table might not have matching rows.
You don't really need to use subqueries, inline views or CTEs here though; you can just join the tables and have the aggregates in the top-level query - you need to duplicate the count not the whole subquery:
with ta as (
select id, count(*) as processed from tbl_account group by id
), tra as (
select id, count(*) as rejected from tbl_rejected_account group by id
)
select tc.id, count(ta.id) as processed,
count(tra.id) as rejected,
count(ta.id) - count(tra.id) as approved
from tbl_control tc
join tbl_approved ta on ta.id = tc.id
join tbl_rejected tra on tra.id = tc.id
group by tc.id
You can add more joins and conditions as needed of course.
Upvotes: 1