SQL Server: select the largest order total from multiple customers with multiple orders, and there are multiple items on each order - sql

I am really stuck on a problem and could use a little help. Here is the problem statement:
"Write the query that will show all the customers, the total of all orders, a count of orders made, the average total of each order, average number of items per order (with decimal points), the largest order total and the smallest order total for each customer. Show every customer even if a customer didn't make an order."
These are the tables:
the lovely tables
I've gotten this far, and I'm hung up on the max order total. I was thinking of a subquery for the highest and lowest order totals but I can't make it work.
SELECT
TC.intCustomerID
,TC.strLastName + ',' + ' ' + TC.strFirstName AS strCustomerName
,ISNULL(SUM( TCOI.intQuantity * TI.monPrice), 0) AS monOrderTotals
,COUNT(DISTINCT TCO.intOrderIndex) AS intNumberOfOrders
,ISNULL(SUM(TCOI.intQuantity * TI.monPrice) / COUNT(DISTINCT TCO.intOrderIndex), 0) AS monAverageOrderTotals
,(SELECT MAX(TCOI.intQuantity * TI.monPrice)
FROM TItems AS TI, TCustomerOrderItems AS TCOI
WHERE TI.intItemID = TCOI.intItemID
-- Cross-query join with two columns
-- AND TC.intCustomerID = TCOI.intCustomerID
-- AND TCO.intOrderIndex = TCOI.intOrderIndex
----GROUP BY
-- TCOI.intCustomerID
--,TCOI.intOrderIndex
) AS monMostExpensiveOrder
FROM
TCustomers AS TC
LEFT OUTER JOIN
TCustomerOrders AS TCO ON (TC.intCustomerID = TCO.intCustomerID)
LEFT OUTER JOIN
TCustomerOrderItems AS TCOI ON (TCO.intOrderIndex = TCOI.intOrderIndex)
LEFT OUTER JOIN
TItems AS TI ON (TCOI.intItemID = TI.intItemID)
GROUP BY
TC.intCustomerID
,TC.strLastName
,TC.strFirstName
Any insight would be greatly appreciated.

For me, using a common table expression goes a long way towards making code easier to read and write when you are working with derived tables (selecting from subqueries).
I think this should cover what you are trying to do, but I was not sure which way you wanted to count average items per order (by number of distinct items or the quantity of items):
with cte as (
select
tc.intCustomerId
, tc.strFirstName
, tc.strLastName
, tcoi.intOrderIndex
, TotalPrice = isnull(sum(tcoi.intQuantity * ti.monPrice), 0 )
, ItemCount = count(*)
, TotalItemQuantity = sum(tcoi.intQuantity)
from TCustomers tc
left join tCustomerOrderItems as tcoi
on tc.intCustomerId = tcoi.intCustomerId
left join tItems as ti
on ti.intItemID = tcoi.intItemID
)
select
intCustomerId
, Name = isnull(strLastName+', ') + isnull(strFirstName,'')
, countOrders = count(intOrderIndex)
, sumTotalPrice = sum(TotalPrice)
, minTotalPrice = min(TotalPrice)
, maxTotalPrice = max(TotalPrice)
, avgTotalPrice = avg(TotalPrice)
, avgItemCount = (sum(ItemCount)+.0)/nullif(count(intOrderIndex),0)
, avgItemQuant = (sum(TotalItemQuantity)+.0)/nullif(count(intOrderIndex),0)
from cte
group by
intCustomerId
, strFirstName
, strLastName
To take out the cte part, you would just move the query into the from.
select
intCustomerId
, Name = isnull(strLastName+', ') + isnull(strFirstName,'')
, countOrders = count(intOrderIndex)
, sumTotalPrice = sum(TotalPrice)
, minTotalPrice = min(TotalPrice)
, maxTotalPrice = max(TotalPrice)
, avgTotalPrice = avg(TotalPrice)
, avgItemCount = (sum(ItemCount)+.0)/nullif(count(intOrderIndex),0)
, avgItemQuant = (sum(TotalItemQuantity)+.0)/nullif(count(intOrderIndex),0)
from (
select
tc.intCustomerId
, tc.strFirstName
, tc.strLastName
, tcoi.intOrderIndex
, TotalPrice = isnull(sum(tcoi.intQuantity * ti.monPrice), 0 )
, ItemCount = count(*)
, TotalItemQuantity = sum(tcoi.intQuantity)
from TCustomers tc
left join tCustomerOrderItems as tcoi
on tc.intCustomerId = tcoi.intCustomerId
left join tItems as ti
on ti.intItemID = tcoi.intItemID
) as cte
group by
intCustomerId
, strFirstName
, strLastName

You will first need to calculate totals per order and per customer.
I will say that the schema is deficient in not storing order totals, since item price is likely to change, and TCustomerOrders likely includes historical orders. Prefixing tables and column names is also not recommended.
WITH CustomerOrders AS
(
SELECT
oi.intCustomerID as CustomerID,
oi.intOrderIndex as OrderID,
SUM(oi.intQuantity * i.monPrice) as SalesAmount,
COUNT(DISTINCT oi.intItemID) as DistinctItemCount,
SUM(oi.intQuantity) as ItemCount
FROM TCustomerOrderItems as oi
INNER JOIN TItems as i on oi.intItemID = i.intItemID
GROUP BY oi.intCustomerID, oi.intOrderIndex
),
CustomerSales AS
(
SELECT
co.CustomerID,
SUM(co.SalesAmount) as TotalSalesAmount,
COUNT(*) as OrderCount,
AVG(co.SalesAmount) as AvgOrderSalesAmount,
-- If item count should be distinct SKU's, use DistinctItemCount
-- Cast to numeric or another non-integer type to get fractional averages
AVG(CAST(co.ItemCount as numeric(14,4)) as AvgItemCount,
MIN(co.SalesAmount) as SmallestOrderSalesAmount,
MAX(co.SalesAmount) as LargestOrderSalesAmount
FROM CustomerOrders co
GROUP BY co.CustomerID
)
SELECT
c.intCustomerID as CustomerID,
c.strFirstName as CustomerFirstName,
c.strLastName as CustomerLastName,
COALESCE(cs.TotalSalesAmount, 0) as TotalSalesAmount,
COALESCE(cs.OrderCount, 0) as OrderCount,
COALESCE(cs.AvgOrderSalesAmount, 0) as AvgOrderSalesAmount,
COALESCE(cs.AvgItemCount, 0) as AvgItemCount,
COALESCE(cs.SmallestOrderSalesAmount, 0) as SmallestOrderSalesAmount,
COALESCE(cs.LargestOrderSalesAmount, 0) as LargestOrderSalesAmount
FROM TCustomers c
LEFT OUTER JOIN CustomerSales cs on c.intCustomerID = cs.CustomerID;

Related

How to write Multiple Sum amount query in select statement using SQL for fast performance

I have writen a query below which is working fine for my report
declare #orgId int=3,
#Year int=2022
;with cte as (
select t.requestNo,year(timeStamp) dispensedInYear from txnhistory(NOLOCK) t where t.categoryNo=411 and t.statusNO=76 and t.companyId=#orgId and
(#Year=0 or (year(t.Timestamp)=#Year ))
)
select distinct p.personid as personId,p.firstName+' '+p.lastname Fitter,
(SELECT ISNULL( ROUND(SUM(amountPaid),3),0) PaidAmount FROM commissionPaid where commissionType='fitter' and personid=cp.personid and statusNo=452 and (#Year=0 or (year(dispensedSignDate)=#Year ))) as total,
(select ISNULL( ROUND(SUM(plt.allowedPrice),3),0) from commissionPaid cp1
inner join ProfitOrLossTable plt on cp1.doNumber=plt.doid where
cp1.personId=cp.personId)BillableAmount,
from cte as r
join productrequestall pr on r.requestNo=pr.requestId --and cp.paymentType='Sales Commission'
join commissionPaid cp on cp.doNumber=pr.doId and cp.commissionType='fitter' and cp.statusNo=452
join commissionratepaid crp on crp.doNumber=cp.doNumber and crp.commissionType=cp.commissionType
join employeecheck ec on ec.employeeCheckId=cp.checkNumber
join person p on p.personId=cp.personId
join fitterCommissionRates fr(NOLOCK) on fr.fitterId=cp.personId and fr.organizationId=#orgId
But is this correct way to write in below line in query because I have other same 3 sum amount counts
(SELECT ISNULL( ROUND(SUM(amountPaid),3),0) PaidAmount FROM commissionPaid where commissionType='fitter' and personid=cp.personid and statusNo=452 and (#Year=0 or (year(dispensedSignDate)=#Year ))) as total
or other way to write above line using left join or sub query to fast report performance and avoid to query timeout issue.
I have modified your query then it is working.
declare
#orgId int = 3,
#Year int = 2021;
select
p.personid,
max( p.firstName +' '+ p.lastname ) Fitter,
coalesce( sum( cp.PaidAmount ), 0 ) PaidAmount
from
txnhistory r
join productrequestall pr
on r.requestNo = pr.requestId
-- and cp.paymentType='Sales Commission'
join
(
SELECT
personid,
doNumber,
ROUND( SUM( amountPaid ), 3) PaidAmount
FROM
commissionPaid
where
commissionType = 'fitter'
and statusNo = 452
and #Year in ( 0, year(dispensedSignDate))
group by
personId,
doNumber,commissionType ) cp
on pr.doId = cp.doNumber
AND pr.doId = cp.doNumber
join commissionratepaid crp
on cp.doNumber = crp.doNumber
and crp.commissionType='fitter'
join person p
on cp.personId = p.personId
join fitterCommissionRates fr
on cp.personId = fr.fitterId
and fr.organizationId = #orgId
where
r.categoryNo = 411
and r.statusNO = 76
and r.companyId = #orgId
and #Year in ( 0, year(r.Timestamp))
group by
p.personid
It APPEARS you are trying to get total commissions (and/or other amounts you are trying to aggregate) based on each given person (fitter). You want to see if there is a way to optimize vs writing 3 separate queries for the respective 3 columns you want aggregated, but all appear to be coming from the same commission paid table (which makes sense). By doing repeated conditional querying per column can be very resource intense, especially with larger data.
What you should probably do is a pre-aggregate of the commission based on the given person AND item based on its qualified criteria. This is done once for the whole query, THEN apply a join based on both parts matching the preceeding ProductRequestALl table content.
The outer query can apply a SUM() of those pre-queried amounts as the outer total is per single person, not based on the person and each "DoID" entry they had in their underlying commission records.
For the outermost query, since I am doing a group by person, but you want to see the name, I am applying a MAX() of the person's name. Since that will never change based on the ID, ID = 1 for "Steve" will always be "Steve", so applying a MAX() eliminates the need of adding the name portion to the GROUP BY clause.
Something like below, and obviously, I dont know your other columns you want aggregated, but think you can get the concept of it.
declare
#orgId int = 3,
#Year int = 2022;
select
p.personid,
max( p.firstName +' '+ p.lastname ) Fitter,
coalesce( sum( cp.PaidAmount ), 0 ) PaidAmount,
coalesce( sum( cp.SecondAmount ), 0 ) SecondAmount,
coalesce( sum( cp.ThirdAmount ), 0 ) ThirdAmount
from
txnhistory r
join productrequestall pr
on r.requestNo = pr.requestId
-- and cp.paymentType='Sales Commission'
join
(
SELECT
personid,
doNumber,
ROUND( SUM( amountPaid ), 3) PaidAmount,
ROUND( SUM( OtherAmount2 ), 3) SecondAmount,
ROUND( SUM( ThirdAmoundColumn ), 3) ThirdAmount
FROM
commissionPaid
where
commissionType = 'fitter'
and statusNo = 452
and #Year in ( 0, year(dispensedSignDate))
group by
personId,
doNumber ) cp
on pr.personid = cp.personid
AND pr.doId = cp.doNumber
join commissionratepaid crp
on cp.doNumber = crp.doNumber
and cp.commissionType = crp.commissionType
join employeecheck ec
on cp.checkNumber = ec.employeeCheckId
join person p
on cp.personId = p.personId
join fitterCommissionRates fr
on cp.personId = fr.fitterId
and fr.organizationId = #orgId
where
r.categoryNo = 411
and r.statusNO = 76
and r.companyId = #orgId
and #Year in ( 0, year(r.Timestamp))
group by
p.personid
Now, you also had an IFNULL() consideration, such as someone does not have any commission. If that is the case, do you still need to see that person even if they never earned a commission? If so, then a left-join MIGHT be applicable.
This query also does away with the "WITH CTE" construct.

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).

Working Out a Percentage of a Count Total

Morning All
Ok so I know how to get the percentage using like.
ROUND(CAST(SUM(Col1)AS FLOAT) *100.0 / COUNT(*),2)
But here is where I am Stuck.
DECLARE #pYWK INT
SET #pYWK = (SELECT YWK FROM CHDS_Management.dbo.Calendar
WHERE DT = (SELECT DATEADD(WEEK,-3, CONVERT(DATE,GETDATE()))));
SELECT
ORD.ProductWhsLocation AS 'Location',
COUNT(ORD.ProductWhsLocation) AS 'Picked'
FROM CHDS_Common.dbo.OMOrder AS ORD
INNER JOIN CHDS_Management.dbo.PickZoneControl AS PZC ON
LEFT(ORD.ProductWhsLocation,3) = PZC.PickZone
INNER JOIN CHDS_Management.dbo.Calendar AS CAL ON CAL.DT =
ORD.EarliestPickDate
WHERE CAL.YWK = #pYWK AND ORD.PickedQty <> 0
GROUP BY ORD.ProductWhsLocation
What I am trying to work out is the % of what was picked from each loaction from the total picked.
Its Monday Morning here so I am sorry if its somthing stupid I am missing.
Thank you for any help on this one.
This is a tricky question, because to obtain the percentages of each group (requiring one aggregation) we need to normalize those counts with the total count of the entire query (another aggregation). One approach is to place the base join query into a CTE. Then, query that CTE and also get the total count via a subquery on the same CTE.
WITH cte AS (
SELECT
ORD.ProductWhsLocation AS 'Location'
FROM CHDS_Common.dbo.OMOrder AS ORD
INNER JOIN CHDS_Management.dbo.PickZoneControl AS PZC
ON LEFT(ORD.ProductWhsLocation,3) = PZC.PickZone
INNER JOIN CHDS_Management.dbo.Calendar AS CAL
ON CAL.DT = ORD.EarliestPickDate
WHERE CAL.YWK = #pYWK AND ORD.PickedQty <> 0
)
SELECT
Location,
COUNT(Location),
ROUND(100.0 * COUNT(Location) / (SELECT COUNT(*) FROM cte), 2) AS pct
FROM cte
GROUP BY
Location;
Use Count(*)Over() to get the total number of location, use it to divide the Picked to get the percentage of picked in each location
SELECT ORD.ProductWhsLocation AS 'Location',
Count(ORD.ProductWhsLocation) AS 'Picked',
( ( Count(ORD.ProductWhsLocation) * 1.0 ) / Sum(Count(ORD.ProductWhsLocation)) OVER() ) * 100.0
FROM CHDS_Common.dbo.OMOrder AS ORD
INNER JOIN CHDS_Management.dbo.PickZoneControl AS PZC
ON LEFT(ORD.ProductWhsLocation, 3) = PZC.PickZone
INNER JOIN CHDS_Management.dbo.Calendar AS CAL
ON CAL.DT = ORD.EarliestPickDate
WHERE CAL.YWK = #pYWK
AND ORD.PickedQty <> 0
GROUP BY ORD.ProductWhsLocation

Error With total Column which calculate the summation of Row values

I created a pivot query which calculate the sum of specific transaction and i want to add additional column which calculate the sum of all transaction for every ID, But my total column give me nulls only for all IDs, Any one can help with that?
this is my Query:
SELECT
AccountID
, OpeningBalance
, OpeningBalanceStatus
, ISNULL([CI], 0) AS CI
, ISNULL([CO], 0) AS CO
, ISNULL([SI], 0) AS SI
, ISNULL([CN], 0) AS CN
, ISNULL([PI], 0) AS PI
, ISNULL([JE], 0) AS JE
, ISNULL([NR], 0) AS NR
, [OpeningBalance]+[CI]+[CO]+[SI]+[CN]+[PI]+[JE]+[NR] AS TOTAL
FROM (SELECT
Accounting.AccDocumentDetails.AccountID
, Accounting.AccDocumentDetails.AmountStatus
, Accounting.AccAccounts.AccountType
, Accounting.AccDocumentHeader.CodeTypePart
, AccAccounts_1.OpeningBalance
, AccAccounts_1.OpeningBalanceStatus
, CASE
WHEN AmountStatus = 'd'
THEN (Amount * 1)
WHEN AmountStatus = 'C'
THEN (Amount * - 1)
END AS NewAmount FROM Accounting.AccDocumentDetails
INNER JOIN Accounting.AccAccounts
ON Accounting.AccDocumentDetails.AccountID = Accounting.AccAccounts.ID
INNER JOIN Accounting.AccChartOfAccounts
ON Accounting.AccChartOfAccounts.ID = Accounting.AccAccounts.ParentNode
INNER JOIN Accounting.AccDocumentHeader
ON Accounting.AccDocumentDetails.AccDocumentHeaderID = Accounting.AccDocumentHeader.ID
INNER JOIN Accounting.AccAccounts AS AccAccounts_1
ON Accounting.AccDocumentDetails.AccountID = AccAccounts_1.ID) AS PivotSelect PIVOT( SUM(NewAmount) FOR CodeTypePart IN ([ci],[CO],[SI],[CN],[PI],[JE],[NR]) ) AS PVT
and this is my output
enter image description here
One way to have the total column is you can use your query as sub query, then create the computation for the total on the outer query. Or you can use cte as well
WITH t_pvt AS (
SELECT AccountID
,OpeningBalance
,OpeningBalanceStatus
,ISNULL([CI], 0) AS CI
,ISNULL([CO], 0) AS CO
,ISNULL([SI], 0) AS SI
,ISNULL([CN], 0) AS CN
,ISNULL([PI], 0) AS PI
,ISNULL([JE], 0) AS JE
,ISNULL([NR], 0) AS NR
FROM (SELECT Accounting.AccDocumentDetails.AccountID
,Accounting.AccDocumentDetails.AmountStatus
,Accounting.AccAccounts.AccountType
,Accounting.AccDocumentHeader.CodeTypePart
,AccAccounts_1.OpeningBalance
,AccAccounts_1.OpeningBalanceStatus
,CASE WHEN AmountStatus = 'd'
THEN (Amount * 1)
WHEN AmountStatus = 'C'
THEN (Amount * - 1)
END AS NewAmount
FROM Accounting.AccDocumentDetails
INNER JOIN Accounting.AccAccounts
ON Accounting.AccDocumentDetails.AccountID = Accounting.AccAccounts.ID
INNER JOIN Accounting.AccChartOfAccounts
ON Accounting.AccChartOfAccounts.ID = Accounting.AccAccounts.ParentNode
INNER JOIN Accounting.AccDocumentHeader
ON Accounting.AccDocumentDetails.AccDocumentHeaderID = Accounting.AccDocumentHeader.ID
INNER JOIN Accounting.AccAccounts AS AccAccounts_1
ON Accounting.AccDocumentDetails.AccountID = AccAccounts_1.ID) AS PivotSelect
PIVOT (SUM(NewAmount)
FOR CodeTypePart IN ([ci],[CO],[SI],[CN],[PI],[JE],[NR])) AS PVT
)
SELECT *
,[OpeningBalance]+[CI]+[CO]+[SI]+[CN]+[PI]+[JE]+[NR] AS TOTAL
FROM t_pvt
With CTE
AS
( select column1 as c1 from tbl)
Select c1 from CTE
thats a simple example of CTE syntax and how you can use it

Get Distinct results of all columns based on MAX DATE of one

Using SQL Server 2012
I have seen a few threads about this topic but I can't find one that involves multiple joins in the query. I can't create a VIEW on this database so the joins are needed.
The Query
SELECT
p.Price
,s.Type
,s.Symbol
, MAX(d.Date) Maxed
FROM AdventDW.dbo.FactPrices p
INNER JOIN dbo.DimSecurityMaster s
ON s.SecurityID = p.SecurityID
INNER JOIN dbo.DimDateTime d
ON
p.DateTimeKey = d.DateTimeKey
GROUP BY p.Price ,
s.Type ,
s.Symbol
ORDER BY s.Symbol
The query works but does not produce distinct results. I am using Order by to validate the results, but it is not required once I get it working. I The result set looks like this.
Price Type Symbol Maxed
10.57 bfus *bbkd 3/31/1989
10.77 bfus *bbkd 2/28/1990
100.74049 cbus 001397AA6 8/2/2005
100.8161 cbus 001397AA6 7/21/2005
The result set I want is
Price Type Symbol Maxed
10.77 bfus *bbkd 2/28/1990
100.74049 cbus 001397AA6 8/2/2005
Here were a few other StackOverflow threads I tried but couldn't get t work with my specific query
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
SQL Selecting distinct rows from multiple columns based on max value in one column
If you want data for the maximum date, use row_number() rather than group by:
SELECT ts.*
FROM (SELECT p.Price, s.Type, s.Symbol, d.Date,
ROW_NUMBER() OVER (PARTITION BY s.Type, s.Symbol
ORDER BY d.Date DESC
) as seqnum
FROM AdventDW.dbo.FactPrices p INNER JOIN
dbo.DimSecurityMaster s
ON s.SecurityID = p.SecurityID INNER JOIN
dbo.DimDateTime d
ON p.DateTimeKey = d.DateTimeKey
) ts
WHERE seqnum = 1
ORDER BY s.Symbol;
You should use a derived table since you really only want to group the DateTimeKey table to get the MAX date.
SELECT p.Price ,
s.Type ,
s.Symbol ,
tmp.MaxDate
FROM AdventDW.dbo.FactPrices p
INNER JOIN dbo.DimSecurityMaster s ON s.SecurityID = p.SecurityID
INNER JOIN
( SELECT MAX(d.Date) AS MaxDate ,
d.DateTimeKey
FROM dbo.DimDateTime d
GROUP BY d.DateTimeKey ) tmp ON p.DateTimeKey = tmp.DateTimeKey
ORDER BY s.Symbol;
/*
this is your initial select which is fine because this is base from your original criteria,
I cannot ignore this so i'll keep this in-tact. Instead from here i'll create a temp
*/
SELECT
p.Price
, s.Type
, s.Symbol
, MAX(d.Date) Maxed
INTO #tmpT
FROM AdventDW.dbo.FactPrices p
INNER JOIN dbo.DimSecurityMaster s
ON s.SecurityID = p.SecurityID
INNER JOIN dbo.DimDateTime d
ON p.DateTimeKey = d.DateTimeKey
GROUP BY p.Price ,
s.Type ,
s.Symbol
ORDER BY s.Symbol
SELECT innerTable.Price, innerTable.Symbol, innerTable.Type, innerTable.Maxed
FROM (
SELECT
ROW_NUMBER () OVER (PARTITION BY t1.Symbol, t1.Type, t1.Maxed ORDER BY t1.Maxed DESC) as row
, *
FROM #tmpT AS t1
) AS innerTable
WHERE row = 1
DROP TABLE #tmpT