SQL combining multiple select statements into a single query - sql

I have the following query which gets the total outstanding invoices and removed the total payments and credit notes to get the outstanding balance.
declare #tInv decimal(19, 2)
declare #tCrn decimal(19, 2)
declare #tPay decimal(19, 2)
set #tInv =
(
SELECT SUM(ST_Unallocated) from Transactions where ST_COPYCUST = 'LOEH001' and ST_TRANTYPE = 'INV'
)
set #tCrn =
(
SELECT SUM(ST_Unallocated) from Transactions where ST_COPYCUST = 'LOEH001' and ST_TRANTYPE = 'CRN'
)
set #tPay =
(
SELECT SUM(ST_Unallocated) from Transactions where ST_COPYCUST = 'LOEH001' and ST_TRANTYPE = 'PAY'
)
declare #currBal decimal(19, 2)
set #currBal =
(
SELECT #tInv - #tPay - #tCrn
)
select #currBal
I want to combine the above query with the below query to show the total outstanding balance for each customer -
select
c.AccountNumber,
c.CustomerID,
c.FullName,
ct.Description as 'CustomerTypeDesc',
c.TelNumber,
c.EmailAddress
from Customers c
inner join CustomerTypes ct on c.CustomerType = ct.TypeID
left join Transactions t on c.AccountNumber = ST_COPYCUST
where c.StatusID = 0 or c.StatusID = 1
Any ideas how I can do this?
Thanks

Try the following query. I have made a few assumptions and have removed the join on the Transactions table from your primary query as I think this is surplus to requirements. The beauty of using these inline queries is that you can return more than one customer if required (by removing the filter on c.AccountNumber):
SELECT
c.AccountNumber
, c.CustomerID
, c.FullName
, ct.Description as 'CustomerTypeDesc'
, c.TelNumber
, c.EmailAddress
, (SELECT SUM(ST_Unallocated) from Transactions where ST_COPYCUST = c.AccountNumber and ST_TRANTYPE = 'INV') -
(SELECT SUM(ST_Unallocated) from Transactions where ST_COPYCUST = c.AccountNumber and ST_TRANTYPE = 'CRN') -
(SELECT SUM(ST_Unallocated) from Transactions where ST_COPYCUST = c.AccountNumber and ST_TRANTYPE = 'PAY') AS BalanceToPay
FROM Customers c
INNER JOIN CustomerTypes ct on c.CustomerType = ct.TypeID
WHERE c.StatusID IN (0,1) AND c.AccountNumber = ST_COPYCUST

Hope didn't broke it, should be faster than with subqueries:
SELECT
c.AccountNumber
, c.CustomerID
, c.FullName
, ct.Description as 'CustomerTypeDesc'
, c.TelNumber
, c.EmailAddress
, SUM(CASE WHEN ST_TRANTYPE = 'INV' THEN t.ST_Unallocated ELSE 0 END) AS tInv
, SUM(CASE WHEN ST_TRANTYPE = 'CRN' THEN t.ST_Unallocated ELSE 0 END) AS tCRN
, SUM(CASE WHEN ST_TRANTYPE = 'PAY' THEN t.ST_Unallocated ELSE 0 END) AS tPAY
, SUM(CASE WHEN ST_TRANTYPE = 'INV' THEN t.ST_Unallocated ELSE 0 END) -
SUM(CASE WHEN ST_TRANTYPE = 'PAY' THEN t.ST_Unallocated ELSE 0 END) -
SUM(CASE WHEN ST_TRANTYPE = 'CRN' THEN t.ST_Unallocated ELSE 0 END) as currBal
FROM Customers c
INNER JOIN CustomerTypes ct on c.CustomerType = ct.TypeID
LEFT JOIN Transactions t on c.AccountNumber = t.ST_COPYCUST
WHERE c.StatusID = 0 or c.StatusID = 1 AND c.AccountNumber = ST_COPYCUST
GROUP BY c.AccountNumber
, c.CustomerID
, c.FullName
, ct.Description
, c.TelNumber
, c.EmailAddress

Related

How to get biggest value from 2 or more fields in a subquery

I have a table with customers that I join with a fact table with sales, based on invoices.
What I need from my report is to get in first part the biggest value of sales based on the incoming order type (1,2,3,C,D) for a customer for last year. And in the second part to get the same but for current year. What I get as result from my current query is all incoming order types with the customer revenue made for each of them. I tried with outer apply as subquery to get only the top 1 value ordered by revenue descending, but in the result I get the same - For all order types the customer revenue. Please help! I hope my explanation isn't understood only by me (happens a lot..)
use dwh01;
WITH OrderTypeUsedLY AS
(
SELECT
c.CustomerKey
,c.BranchId
,c.CustomerId
,c.CustomerName
,ISNULL(SUM(y.[Sale_Revenue]), 0) as [Sale_Revenue_LY]
,ISNULL(SUM(y.[Sale_GrossMarginTotal]), 0) as [Sale_GrossMarginTotal_LY]
,y.IncomingOrderTypeId as IncomingOrderType_LY
FROM live.DimCustomer c
left join (SELECT s.CustomerKey,iot.IncomingOrderTypeid, s.[Sale_Revenue], s.[Sale_GrossMarginTotal] FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d
on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType iot on iot.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where s.ReportCurrencyId = 'LC'
and D.Year = YEAR(GETDATE())-1 --- Last Year
) y on c.CustomerKey = y.CustomerKey
where c.CustomerKey = '157053'
group by c.CustomerKey, c.CustomerId, c.CustomerName, c.BranchId, y.IncomingOrderTypeId
),
--*********************************************************************************************************************************--
OrderTypeCY as(
SELECT
c.CustomerKey
,c.BranchId
,c.SalesRepKey
,c.CustomerId
,c.CustomerName
,ISNULL(SUM(y.[Sale_Revenue]), 0) as [Sale_Revenue_CY]
,ISNULL(SUM(y.[Sale_GrossMarginTotal]), 0) as [Sale_GrossMarginTotal_CY]
,y.IncomingOrderTypeId as IncomingOrderType_CY
FROM live.DimCustomer c
left join (SELECT s.CustomerKey,iot.IncomingOrderTypeid, s.[Sale_Revenue], s.[Sale_GrossMarginTotal] FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d
on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType iot on iot.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where s.ReportCurrencyId = 'LC'
and D.Year = YEAR(GETDATE()) --- Current Year
) y on c.CustomerKey = y.CustomerKey
where c.CustomerKey = '157053'
group by c.CustomerKey, c.CustomerId, c.CustomerName, c.BranchId, y.IncomingOrderTypeId, c.SalesRepKey
)
--*********************************************************************************************************************************--
SELECT
otly.BranchId,
rep.SalesRepId,
rep.SalesRepName,
otly.CustomerId,
otly.CustomerName,
otly.Sale_Revenue_LY,
otly.Sale_GrossMarginTotal_LY,
IncomingOrderType_LY,
otcy.Sale_Revenue_CY,
otcy.Sale_GrossMarginTotal_CY,
IncomingOrderType_CY
from OrderTypeUsedLY otly
left join OrderTypeCY otcy
on otly.CustomerKey = otcy.CustomerKey
join live.DimCustomer cus on cus.CustomerKey = otcy.CustomerKey
join live.DimSalesRep rep on rep.SalesRepKey = otcy.SalesRepKey
order by otcy.Sale_Revenue_CY desc, otly.Sale_Revenue_LY desc
,rep.SalesRepId
And here is the outer apply I tried:
outer apply (
SELECT top 1
iot.IncomingOrderTypeId,
Sale_Revenue
FROM [dwh01].[live].DimIncomingOrderType iot
where iot.IncomingOrderTypeKey = y.IncomingOrderTypeKey
order by Sale_Revenue desc) x
In the first select ( with OrderTypeUsed_LY ) I get this:
And I get the same in the second select, but with the values for current year.
The purpose of the report is to see the difference in the incoming order type most used (most profit made with it) for a customer last year and to see if he continues to use it this year, or uses another incoming order type this year.
Again I'm sorry for the bad explanation, I'm trying my best (I understand myself very well)
Here is the expected result:
Expected Result
I marked in red the last year part and in green the current year part.
If you change the subquery to:
SELECT
iot.IncomingOrderTypeKey,
MAX(Sale_Revenue)
FROM [dwh01].[live].DimIncomingOrderType iot
GROUP BY iot.IncomingOrderTypeKey
then you can JOIN (not APPLY) directly on IncomingOrderTypeKey AND Sale_Revenue.
Try this:
USE dwh01;
DECLARE #CustomerKey varchar(6) = '157053'
, #ReportCurrencyId varchar(2) = 'LC'
, #CurrentYear int = YEAR(GETDATE())
, #TargetYear int = YEAR(GETDATE())-1
;
WITH FactsTable AS
(
SELECT
s.CustomerKey
, i.IncomingOrderTypeid
, [Sale_Revenue] = ISNULL(s.[Sale_Revenue] , 0)
, [Sale_GrossMarginTotal] = ISNULL(s.[Sale_GrossMarginTotal], 0)
, d.[Year]
FROM [dwh01].[live].[FactSales] s
inner join live.DimDate d on d.DateId = s.PostingDateKey
inner join live.DimIncomingOrderType i on i.IncomingOrderTypeKey = s.IncomingOrderTypeKey
where
s.CustomerKey = #CustomerKey
and s.ReportCurrencyId = #ReportCurrencyId
)
, OrderTypeTable
(
SELECT
c.CustomerKey
, c.BranchId
, c.CustomerId
, c.CustomerName
, c.SalesRepKey
, IncomingOrderType_LY = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.IncomingOrderTypeId ELSE 0 END)
, [Sale_Revenue_LY] = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.[Sale_Revenue] ELSE 0 END)
, [Sale_GrossMarginTotal_LY] = SUM(CASE WHEN y.[Year] = #TargetYear THEN y.[Sale_GrossMarginTotal] ELSE 0 END)
, IncomingOrderType_LY = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.IncomingOrderTypeId ELSE 0 END)
, [Sale_Revenue_CY] = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.[Sale_Revenue] ELSE 0 END)
, [Sale_GrossMarginTotal_CY] = SUM(CASE WHEN y.[Year] = #CurrentYear THEN y.[Sale_GrossMarginTotal] ELSE 0 END)
FROM live.DimCustomer c
left join FactsTable y on y.CustomerKey = c.CustomerKey
group by
c.CustomerKey
, c.BranchId
, c.CustomerId
, c.CustomerName
, y.IncomingOrderTypeId
, c.SalesRepKey
)
SELECT
O.BranchId
, R.SalesRepId
, R.SalesRepName
, O.CustomerId
, O.CustomerName
, O.Sale_Revenue_LY
, O.Sale_GrossMarginTotal_LY
, O.IncomingOrderType_LY
, O.Sale_Revenue_CY
, O..Sale_GrossMarginTotal_CY
, O.IncomingOrderType_CY
from OrderTypeTable O
join live.DimSalesRep R on R.SalesRepKey = O.SalesRepKey
order by
O.Sale_Revenue_CY desc
, O.Sale_Revenue_LY desc
, R.SalesRepId
The solution is with using row_number() function in the inner query of the first CTE:
(
select *, row_number() over (partition by x0.CustomerKey order by x0.Sale_Revenue desc) as rn
from
(
select fs.CustomerKey, iot.IncomingOrderTypeKey,
sum(fs.Sale_Revenue) as Sale_Revenue
FROM [dwh01].[live].DimIncomingOrderType iot
join live.FactSales fs
on iot.IncomingOrderTypeKey = fs.IncomingOrderTypeKey
join live.DimDate d
on d.DateId = fs.PostingDateKey
where d.[year] = #CurrentYear
GROUP BY fs.CustomerKey, iot.IncomingOrderTypeKey
) as x0
) as x1 on x1.CustomerKey = s.CustomerKey
The row_number() function gets only the first row from the result for each customer, and that is with the biggest sale revenue ( order by sale_revenue desc).

Aggregate Function / Group By Clause

Having some minor issues with my query. I am trying just to get sums for a project. I know I am probably missing something super simple but I am getting caught up. If someone could take a look and give me a suggestion on how I can figure this out.
select
(select count(distinct(o1.orderno))
from mck_hvs.orderheader o1 with(nolock)
where o1.orderno = od.orderno and o1.refrigerate = 'Y'
) as TotalColdOrders,
(select count(distinct(o2.orderno))
from mck_hvs.orderdetails o2 with(nolock)
where o2.orderno = od.orderno and o2.drugclass
not in ('null', 'Rx')
) as ControlledOrders,
(select count(distinct(o3.orderno))
from mck_hvs.orderheader o3 with(nolock)
where o3.orderno = od.orderno and o3.pucksideinorder = 'Y' and
o3.totesideinorder = 'N' and o3.numitems > 4
) as RobotOrders,
(select count(distinct(o4.orderno))
from mck_hvs.orderheader o4 with(nolock)
where o4.orderno = od.orderno and o4.pucksideinorder = 'Y' and
o4.totesideinorder = 'Y'
) as ComboOrders,
(select count(distinct(o5.rxnum))
from mck_hvs.orderdetails o5 with(nolock)
where o5.refrigerate = 'Y'
) as TotalColdScripts,
(select count(distinct(o6.rxnum))
from mck_hvs.orderdetails o6 with(nolock)
where o6.orderno = od.orderno and o6.drugclass
not in ('null', 'RX')
) as ControlledScripts,
(select sum(o7.numscripts)
from mck_hvs.orderheader o7 with(nolock)
where o7.orderno = od.orderno and o7.pucksideinorder = 'Y' and
o7.totesideinorder = 'N' and o7.numitems > 4
) as RobotScripts,
(select sum(o8.numscripts)
from mck_hvs.orderheader o8 with(nolock)
where o8.orderno = od.orderno and o8.pucksideinorder = 'Y' and
o8.totesideinorder = 'Y'
) as ComboOrderScripts,
count(distinct(od.orderno)) as TotalOrders,
count(distinct(od.rxnum)) as TotalScripts
from
mck_hvs.orderdetails od with( nolock )
You should try this:
SELECT
od.orderno,
COUNT(DISTINCT
CASE WHEN oh.refrigerate = 'Y' THEN od.orderno END
) AS totalcoldorders,
COUNT(DISTINCT
CASE WHEN od.drugclass NOT IN ('null', 'Rx') THEN od.orderno END
) AS controlledorders,
COUNT(DISTINCT
CASE
WHEN oh.pucksideinorder = 'Y'
AND oh.totesideinorder = 'N' AND oh.numitems > 4
THEN od.orderno
END
) AS robotorders,
COUNT(DISTINCT
CASE
WHEN oh.pucksideinorder = 'Y' AND oh.totesideinorder = 'Y'
THEN oh.orderno
END
) AS comboorders,
COUNT(DISTINCT
CASE WHEN od.refrigerate = 'Y' THEN od.rxnum END
) AS totalcoldscripts,
COUNT(DISTINCT
CASE WHEN od.drugclass NOT IN ('null', 'RX') THEN od.rxnum END
) AS controlledscripts,
SUM(
CASE
WHEN oh.pucksideinorder = 'Y'
AND oh.totesideinorder = 'N' AND oh.numitems > 4
THEN oh.numscripts
END
) AS robotscripts,
SUM(
CASE
WHEN oh.pucksideinorder = 'Y' AND oh.totesideinorder = 'Y'
THEN oh.numscripts
END
) AS comboorderscripts,
(
SELECT COUNT(DISTINCT orderno)
FROM mck_hvs.orderdetails WITH (nolock)
) AS totalorders,
(
SELECT COUNT(DISTINCT rxnum)
FROM mck_hvs.orderdetails WITH (nolock)
) AS totalscripts
FROM mck_hvs.orderdetails od WITH (nolock)
LEFT JOIN mck_hvs.orderheader oh WITH (nolock)
ON oh.orderno = od.orderno
GROUP BY od.orderno
ORDER BY od.orderno;

SQL Server 2012 - is there a better way to do this as when there are duplicates it counts them more than once?

This is not accurate as the count can be wrong so is there a better way using exists? I want to identify if one case of each course exists.
SELECT
IdentityCourses.IdentityID AS ID,Identities.LastName AS LastName,
Identities.FirstNames AS FirstName,Units.UnitID, Units.Description AS Unit
FROM
dbo.UnitIdentities
INNER JOIN
dbo.IdentityCourses ON dbo.UnitIdentities.IdentityID = dbo.IdentityCourses.IdentityID
INNER JOIN
dbo.COCSourceCourses ON dbo.IdentityCourses.CourseID = dbo.COCSourceCourses.CBESCourseID
INNER JOIN
dbo.Identities ON dbo.UnitIdentities.IdentityID = dbo.Identities.IdentityID
INNER JOIN
dbo.Units ON dbo.UnitIdentities.UnitID = dbo.Units.UnitID
WHERE
(dbo.UnitIdentities.IsActiveMember = 1)
GROUP BY
IdentityCourses.IdentityID, Identities.LastName, Identities.FirstNames,
Units.Description, Units.UnitID
HAVING
(SUM((CASE WHEN COCSourceCourses.COCID = 10048 then 1 else 0 end)+
(CASE WHEN COCSourceCourses.COCID = 10049 then 1 else 0 end)+
(CASE WHEN COCSourceCourses.COCID = 10050 then 1 else 0 end)+
(CASE WHEN COCSourceCourses.COCID = 10051 then 1 else 0 end)+
(CASE WHEN COCSourceCourses.COCID = 10063 then 1 else 0 end)+
(CASE WHEN COCSourceCourses.COCID = 10073 then 1 else 0 end))) = 6
AND IdentityCourses.IdentityID NOT IN (SELECT IdentityID
FROM IdentityQualifications
WHERE QualificationID IN (1012, 1014, 1025))
ORDER BY
Units.UnitID
Try using count(distinct ..):
SELECT (..columns..)
FROM dbo.UnitIdentities UI
LEFT JOIN IdentityQualifications IQ
ON IQ.IdentityID = UI.IdentityID
AND IQ.QualificationID IN (1012, 1014, 1025)
INNER JOIN dbo.IdentityCourses IC
ON IC.IdentityID = dbo.UnitIdentities.IdentityID
INNER JOIN dbo.COCSourceCourses COC
ON COC.CBESCourseID = IC.CourseID
AND COC.COCID IN (10048, 10049, 10050, 10051, 10063, 10073)
(..two more table joins on identities and units..)
WHERE IQ.IdentityID IS NULL
GROUP BY (..columns..)
HAVING COUNT(DISTINCT COC.COCID) = 6
ORDER BY Units.UnitID
When you are only interested in certain records, then why don't you use the WHERE clause? Only select the COCIDs you are interested in and then count distinct results.
You don't need any GROUP BY and HAVING by the way, as you only display identities/units, so you can count associated courses in a subquery in your WHERE clause.
select
i.identityid as id,
i.lastname as lastname,
i.firstnames as firstname,
u.unitid,
u.description as unit
from dbo.identities i
join dbo.unitidentities ui on ui.identityid = i.identityid and ui.isactivemember = 1
join dbo.units u on u.unitid = ui.unitid
where i.identityid not in
(
select iq.identityid
from identityqualifications iq
where iq.qualificationid in (1012, 1014, 1025)
)
and
(
select count(distinct sc.cocid)
from dbo.cocsourcecourses sc
join dbo.identitycourses ic on ic.courseid = sc.cbescourseid
where sc.cocid in (10048, 10049, 10050, 10051, 10063, 10073)
and ic.identityid = i.identityid
) = 6
order by u.unitid;

CASE Statement in query

I am trying to return a bunch of values in a table without causing "duplicate" outputs. I thought a CASE statement or derived table may help? Any input would be great.
Within the column Product_code there are the following values
(AFF,E,H,PD,PDM,PDRL,PDRM etc)
Here is my SQL:
SELECT DISTINCT
[Member Id] = c.master_customer_id,
[Full Name] = c.label_name,
[First Name] = c.first_name,
[Last Name] = c.last_name,
[Email] = ISNULL(c.primary_email_address,''),
[Annual Meeting] = MAX(ca.product_code)
CASE WHEN od.product_code IN (AFF,E,H,PD,PDM,PDRL,PDRM) then ??
--[Membership Type] = od.product_code
FROM order_detail od
INNER JOIN customer c
on c.master_customer_id = od.ship_master_customer_id
and c.sub_customer_id = od.ship_sub_customer_id
and od.subsystem = 'MBR'
INNER JOIN cus_activity ca
on ca.master_customer_id = c.master_customer_id
and ca.sub_customer_id = c.sub_customer_id
and ca.subsystem = 'MTG'
and ca.activity_subcode IN ('2012AM', '2011AM')
and ca.product_code IN ('2012AM','2011AM')
INNER JOIN cus_address caddr
on caddr.master_customer_id = c.master_customer_id
and caddr.sub_customer_id = c.sub_customer_id
INNER JOIN cus_address_detail caddrd
on caddrd.cus_address_id = caddr.cus_address_id
where c.customer_class_code NOT IN ('STAFF', 'TEST_MBR')
and c.customer_status_code = 'ACTIVE'
and c.primary_email_address IS NOT NULL
and ca.master_customer_id IN (select order_detail.ship_master_customer_id
from order_detail where order_detail.subsystem = 'MBR')
and caddrd.priority_seq = 0
and caddrd.address_status_code = 'GOOD'
and od.product_code in
( 'AFF','E','H', 'PD','PDM','PDRL','PDRM','PDRU','R',
'RM','RRL','RRM','RRU','S','SM','SRL','SRM','SRU','SU','SUM','SURL','SURM','SURU' )
and od.cycle_end_date >= '01/01/2011' and od.cycle_end_date <= '12/31/2012'
GROUP BY c.master_customer_id,c.label_name,
c.FIRST_NAME,c.LAST_NAME,c.primary_email_address,od.product_code,caddr.country_descr
order by c.master_customer_id
You are looking for a Cross-Tab result (also known as a Pivot table) based on a given customer. You want all possible membership status levels as a person could be multiple levels (per your example).
With the group by on the customer ID, everything will roll-up to the member. So, if there are multiple product codes, I have applied SUM() based on each individual "product_code" you wanted to consider.
Next, to help optimize your query, I would ensure your Order_Detail has an index on
( SubSystem, Product_Code, Cycle_End_Date, ship_master_customer_id )
I've slightly rewritten to better allow myself to follow what you were getting and the criteria related to each table. Hopefully it makes sense to what you started with.
SELECT
c.master_customer_id as [Member Id],
c.label_name as [Full Name],
c.first_name as [First Name],
c.last_name as [Last Name],
ISNULL(c.primary_email_address,'') as [Email],
MAX(ca.product_code) as [Annual Meeting],
SUM( CASE WHEN od.product_code = 'AFF' then 1 else 0 end ) as Membership_AFF,
SUM( CASE WHEN od.product_code = 'E' then 1 else 0 end ) as Membership_E,
SUM( CASE WHEN od.product_code = 'H' then 1 else 0 end ) as Membership_H,
SUM( CASE WHEN od.product_code = 'PD' then 1 else 0 end ) as Membership_PD,
SUM( CASE WHEN od.product_code = 'PDM' then 1 else 0 end ) as Membership_PDM,
SUM( CASE WHEN od.product_code = 'PDRL' then 1 else 0 end ) as Membership_PDRL,
SUM( CASE WHEN od.product_code = 'PDRM' then 1 else 0 end ) as Membership_PDRM
FROM
order_detail od
INNER JOIN customer c
on od.ship_master_customer_id = c.master_customer_id
and od.ship_sub_customer_id = c.sub_customer_id
and c.customer_class_code NOT IN ('STAFF', 'TEST_MBR')
and c.customer_status_code = 'ACTIVE'
and c.primary_email_address IS NOT NULL
INNER JOIN cus_activity ca
on od.ship_master_customer_id = ca.master_customer_id
and od.ship_sub_customer_id = ca.sub_customer_id
and ca.subsystem = 'MTG'
and ca.activity_subcode IN ('2012AM', '2011AM')
and ca.product_code IN ('2012AM','2011AM')
INNER JOIN cus_address caddr
on od.ship_master_customer_id = caddr.master_customer_id
and od.ship_sub_customer_id = caddr.sub_customer_id
INNER JOIN cus_address_detail caddrd
on caddr.cus_address_id = caddrd.cus_address_id
and caddrd.priority_seq = 0
and caddrd.address_status_code = 'GOOD'
WHERE
od.subsystem = 'MBR'
and od.product_code in ( 'AFF','E','H','PD','PDM','PDRL','PDRM','PDRU',
'R','RM','RRL','RRM','RRU','S','SM','SRL',
'SRM','SRU','SU','SUM','SURL','SURM','SURU' )
and od.cycle_end_date >= '01/01/2011'
and od.cycle_end_date <= '12/31/2012'
GROUP BY
od.ship_master_customer_id,
c.label_name,
c.FIRST_NAME,
c.LAST_NAME,
c.primary_email_address,
caddr.country_descr
order by
od.ship_master_customer_id

How can I rewrite this query without repeating SELECT subqueries

I have written a query like this. It is working and giving me the result which I wanted.
I have a SELECT query to get CAR_AMOUNT and HOTEL_AMOUNT.
But, I have to repeat the same SELECT query to get the SUM of both. I am not able to use alias name. How can I avoid this?
SELECT B.EMPLOYEE_ID,
(select SUM(AMOUNT)
FROM travel_reimbursements_items
WHERE type = 'CAR'
AND travel_request_no = B.travel_request_no
AND STATUS='APPROVED') as CAR_AMOUNT,
(select SUM(AMOUNT)
FROM travel_reimbursements_items
WHERE type = 'HOTEL'
AND travel_request_no = B.travel_request_no
AND STATUS='APPROVED') as HOTEL_AMOUNT,
NVL((select SUM(AMOUNT)
FROM travel_reimbursements_items
WHERE type = 'CAR'
AND travel_request_no = B.travel_request_no
AND STATUS='APPROVED'),0)
+NVL((select SUM(AMOUNT)
FROM travel_reimbursements_items
WHERE type = 'HOTEL'
AND travel_request_no = B.travel_request_no
AND STATUS='APPROVED'),0) as TOTAL
FROM TRAVEL_REQUEST_ITEM A
LEFT OUTER JOIN TRAVEL_REQUEST B
ON (B.TRAVEL_REQUEST_NO= A.TRAVEL_REQUEST_SR_NO)
select b.employee_id
, sum(case when c.type = 'CAR' then c.amount end) car_amount
, sum(case when c.type = 'HOTEL' then c.amount end) hotel_amount
, sum(c.amount) total
from travel_request_item a
left outer join travel_request b
on (b.travel_request_no= a.travel_request_sr_no)
left outer join travel_reimbursements_items c
on ( c.travel_request_no = b.travel_request_no
and c.type in ('CAR','HOTEL')
and c.status = 'APPROVED'
)
group by b.employee_id
Regards,
Rob.
This should work in oracle.
SELECT B.EMPLOYEE_ID,
SUM(CASE WHEN C.type = 'CAR' and C.STATUS='APPROVED' THEN C.AMOUNT ELSE 0 END) as CAR_AMOUNT,
SUM(CASE WHEN C.type = 'HOTEL' and C.STATUS='APPROVED' THEN C.AMOUNT ELSE 0 END) as HOTEL_AMOUNT,
SUM(CASE WHEN C.type IN ('CAR', 'HOTEL') and C.STATUS='APPROVED' THEN C.AMOUNT ELSE 0 END) as TOTAL
FROM TRAVEL_REQUEST_ITEM A
LEFT OUTER JOIN TRAVEL_REQUEST B ON (B.TRAVEL_REQUEST_NO= A.TRAVEL_REQUEST_SR_NO)
LEFT OUTER JOIN TRAVEL_REIMBURSEMENTS_ITEMS C ON (C.TRAVEL_REQUEST_NO = A.TRAVEL_REQUEST_SR_NO)
GROUP BY B.EMPLOYEE_ID
Just do a conditional sum based on the item type.