compute Sum of Sum in sql - sql

in SQL when I want to compute Sum of one column that is also Sum base on grouping, the total value is not correct.here I want to compute sum of Mand that is Sum(Qty) but the final result isn't correct.
Select Sum(Mand) from (Select TrackingFactor1 As Number ,SUM(Qty) As Mand from(
Select t.TrackingFactor1,SUM(
CASE
WHEN Direction = 1 THEN t.MajorUnitQuantity
WHEN Direction = 2 THEN -t.MajorUnitQuantity
ELSE 0
END
) AS Qty,
ROW_NUMBER() OVER(ORDER BY i.Date, i.VoucherCreationDate, v.InventoryVoucherID, i.InventoryVoucherItemID) AS
RowNumber
from LGS3.InventoryVoucher AS v
INNER JOIN LGS3.InventoryVoucherItem i ON v.InventoryVoucherID = I.InventoryVoucherRef
LEFT OUTER JOIN LGS3.InventoryVoucherItemTrackingFactor t ON i.InventoryVoucherItemID = t.InventoryVoucherItemRef
GROUP BY
v.InventoryVoucherID,
v.Number,
i.Date,
i.VoucherCreationDate,
i.InventoryVoucherItemID,
i.CounterpartEntityText,
t.TrackingFactor1 ,
v.FiscalYearRef
)As A
group by TrackingFactor1
Having SUM(Qty)>0) As AA

Related

How to select aggregate discount percentages and flat amount?

I have a scenario whereby I need to aggregate n number of discounts to get a total discount. Each discount must be applied net of the previous discount.
For example: I have an order of 200 Rs. (Sum of amount) and I have multiple vouchers. The first gets me 15% off, 200-(200*(15/100)) = 170.
And then we have a second voucher worth Flat 10 Rs., 170-(10) = 160.
Sequence is important, so a further field records the order in which the discounts are applied.
Below are table:
order
id order_id productId amount
1 1 5 160
2 1 9 40
So total amount without discount is: 200 Rs.
discount
id order_id seq type amt
1 1 1 Per (%) 15
2 1 3 Flat 10
So, discount amount will be: ((200*(15/100))) 30 + 10 = 40 .
So I have tried to write SQL query with CTE but it is not giving expected output:
WITH recursive cte_calctotalamount AS
(
SELECT order_id,
sum(amount) AS totalamount
FROM ORDER
WHERE order_id=1
GROUP BY order_id ),
cte_totaldiscountamount AS
(
SELECT i.order_id,
i.seq,
i.amt,
ta.totalamount AS totalamount,
CASE
WHEN i.type='Flat' THEN i.amt
WHEN i.type='Per' THEN (ta.totalamount * (i.amt/100))
END totaldiscountedamount,
(totalamount- (
CASE
WHEN i.type='Flat' THEN i.amt
WHEN i.type='Per' THEN (ta.totalamount * (i.amt/100))
END) ) amountafterdiscount
FROM discount i
INNER JOIN cte_calctotalamount ta
ON ta.order_id=i.order_id
UNION
SELECT d.order_id,
d.seq,
d.amt,
ad.totalamount,
CASE
WHEN d.type='Flat' THEN d.amt
WHEN d.type='Per' THEN (ad.amountafterdiscount - (d.amt/100))
END totaldiscountedamount,
(amountafterdiscount - (
CASE
WHEN d.type='Flat' THEN d.amt
WHEN d.type='Per' THEN (ad.amountafterdiscount - (d.amt/100))
END) ) amountafterdiscount
FROM discount d
INNER JOIN cte_totaldiscountamount ad
ON d.order_id=ad.order_id
AND d.seq=ad.seq+1 )
SELECT *
FROM cte_totaldiscountamount;
Please help to achieve below output,
order_id totalAmount totalDiscountedAmount amountAfterDiscount
1 200 40 160
There are 4 things that you need to modify in your query
In recursive queries, you need to initialize the first result set. It is the basis of calculation of the next iterations. In this case, you will need to add in the first query in the recursive part where i.seq = 1 (we start with the initial discount).
Second, you are not adding the discounted amounts recursively. For that, you need to retrieve the row discount amount from previous iterations. so instead of :
case
when d.type='Flat' THEN d.amt
WHEN d.type='Per' THEN (ad.AmountAfterDiscount - (d.amt/100))
END totalDiscountedAmount
you should be writing:
totalDiscountedAmount + case
when d.type='Flat' THEN d.amt
WHEN d.type='Per' THEN (ad.AmountAfterDiscount - (d.amt/100))
END totalDiscountedAmount
You will need to add a new row incrementor in discounts. Recursive queries will end when the returned result set of the second query after Union is null. Since the the condition d.seq=ad.seq+1 will be false, the query will return nothing. It is due to the fact that in discounts table, your next sequence is 3 and not 2. In the proposed solution, you can see that it is returned in the CTE of discounts using ROW_NUMBER()
Finally, you'll need to keep only the last row (since the recursive query will return naturally N rows if N is the number of discounts for a certain order. You can simply do that by joining the last output with a subquery as shown in the example.
Your final query would look like:
WITH RECURSIVE CTE_CalcTotalAmount
AS
(
select order_id,sum(amount) As totalAmount from "order"
where order_id=1
group by order_id
),
CTE_DiscountsPerOrder as (
select order_id, seq, amt, type, row_number() over (partition by order_id order by seq asc ) as new_seq from discount ) ,
CTE_TotalDiscountAmount AS
(
select i.order_id,i.new_seq,i.amt,ta.totalAmount as TotalAmount,
case
when i.type='Flat' THEN i.amt
WHEN i.type='Per' THEN (ta.totalAmount * (i.amt/100))
END totalDiscountedAmount,
(totalAmount-
(case
when i.type='Flat' THEN i.amt
WHEN i.type='Per' THEN (ta.totalAmount * (i.amt/100))
END)
) AmountAfterDiscount
from CTE_DiscountsPerOrder i
inner JOIN CTE_CalcTotalAmount ta ON ta.order_id=i.order_id
where i.new_seq=1
UNION
select d.order_id,d.new_seq,d.amt,ad.totalAmount,
totalDiscountedAmount+ case
when d.type='Flat' THEN d.amt
WHEN d.type='Per' THEN (ad.AmountAfterDiscount - (d.amt/100))
END totalDiscountedAmount,
(AmountAfterDiscount -
(case
when d.type='Flat' THEN d.amt
WHEN d.type='Per' THEN (ad.AmountAfterDiscount - (d.amt/100))
END)
) amountAfterDiscount
From CTE_DiscountsPerOrder d
inner JOIN CTE_TotalDiscountAmount ad on d.order_id=ad.order_id
AND d.new_seq=ad.new_seq+1
)
select * from CTE_TotalDiscountAmount a
join (select order_id, count(*) as totalDiscounts from CTE_DiscountsPerOrder group by 1) b on b.order_id = a.order_id and b.totalDiscounts = a.new_seq;

How to sum the value of another sum from same select statement

I am trying sum the value of another sum in the same select statement and then I want to check the sum value in case statement. When I do it, it is working instead it is just gets individual value.
I have to sum Billable_Trades and then I have to give some rate if the billable_trades is above some numbers for that, I need to know the total of the billable_trade.
select t.Business_Unit_Description, -- case when Product_Type_Description = 'Fee Based' then 'Fee Based' else '' end as revenue_type,
billable_trades,
isnull(c.comm_adjustments, 0) as commission_adjustments,
rate,
billable_trades*rate as charges,
0.3 as commission_rate,
isnull(c.comm_adjustments, 0)*0.3 as credit,
(billable_trades*rate)- isnull(c.comm_adjustments, 0)*0.3 as total
from
(
select Business_Unit_Description,
sum(billable_trades) as billable_trades,
CASE WHEN SUM(billable_trades) > 0 and SUM(billable_trades) <= 150000 THEN 0.85667 ELSE 0.47104 END as rate
from cte_combined
group by Business_Unit_Description
) t
left outer join cte_comm_adj c on c.Business_Unit_Description = t.Business_Unit_Description
order by t.Business_Unit_Description
There is obviously more to the query than is shown - as you are using a derived table to reference a CTE and also outer joining to another CTE.
I would move the calculation of rate out of the derived table:
Select t.Business_Unit_Description -- case when Product_Type_Description = 'Fee Based' then 'Fee Based' else '' end as revenue_type,
, t.sum_billable_trades
, commission_adjustments = isnull(c.comm_adjustments, 0)
, r.rate
, charges = t.sum_billable_trades * r.rate
, commission_rate = 0.3
, credit = isnull(c.comm_adjustments, 0) * 0.3
, total = (t.sum_billable_trades * r.rate) - isnull(c.comm_adjustments, 0) * 0.3
From (Select Business_Unit_Description
, sum_billable_trades = sum(billable_trades)
From cte_combined
Group By Business_Unit_Description) t
Cross Apply (Values (iif(t.sum_billable_trades > 0 And t.sum_billable_trades <= 150000, 0.85667, 0.47104))) As r(rate)
Left Outer Join cte_comm_adj c On c.Business_Unit_Description = t.Business_Unit_Description
Order By t.Business_Unit_Description;
I also wouldn't use the same name for the sum just to make it clearer.

SQL - ROW_NUMBER that is used in a multi-condition LEFT JOIN

Two tables store different properties for each product: CTI_ROUTING_VIEW and ORD_MACH_OPS
They are both organized by SPEC_NO > MACH_SEQ_NO but the format of the Sequence number is different for each table so it can't be used for a JOIN. ORCH_MACH_OPS has MACHINE and PASS_NO, meaning if a product goes through the same machine twice, the row with the higher SEQ_NO will be PASS_NO 2, 3, etc. CTI_ROUTING_VIEW does not offer PASS_NO, but I can achieve the desired result with:
SELECT TOP (1000) [SPEC_NO]
,[SPEC_PART_NO]
,[MACH_NO]
,[MACH_SEQ_NO]
,[BLANK_WID]
,[BLANK_LEN]
,[NO_OUT_WID]
,[NO_OUT_LEN]
,[SU_MINUTES]
,[RUN_SPEED]
,[NO_COLORS]
,[PRINTDIEID]
,[CUTDIEID]
,ROW_NUMBER() OVER (PARTITION BY MACH_NO ORDER BY MACH_SEQ_NO) as PASS_NO
FROM [CREATIVE].[dbo].[CTI_ROUTING_VIEW]
I would think that I could use this artificial PASS_NO as a JOIN condition, but I can't seem to get it to come through. This is my first time using ROW_NUMBER() so I'm just wondering if I'm doing something wrong in the JOIN syntax.
SELECT rOrd.[SPEC_NO]
,rOrd.[MACH_SEQ_NO]
,rOrd.[WAS_REROUTED]
,rOrd.[NO_OUT]
,rOrd.[PART_COMP_FLG]
,rOrd.[SCHED_START]
,rOrd.[SCHED_STOP]
,rOrd.[MACH_REROUTE_FLG]
,rOrd.[MACH_DESCR]
,rOrd.REPLACED_MACH_NO
,rOrd.MACH_NO
,rOrd.PASS_NO
,rWip.MAX_TRX_DATETIME
,ISNULL(rWip.NET_FG_SUM*rOrd.NO_OUT,0) as NET_FG_SUM
,CASE
WHEN rCti.BLANK_WID IS NULL then 'N//A'
ELSE CONCAT(rCti.BLANK_WID, ' X ', rCti.BLANK_LEN)
END AS SIZE
,ISNULL(rCti.PRINTDIEID,'N//A') as PRINTDIEID
,ISNULL(rCti.CUTDIEID, 'N//A') as CUTDIEID
,rStyle.DESCR as STYLE
,ISNULL(rCti.NO_COLORS, 0) as NO_COLORS
,CAST(CONCAT(rOrd.ORDER_NO,'-',rOrd.ORDER_PART_NO) as varchar) as ORD_MACH_KEY
FROM [CREATIVE].[dbo].[ORD_MACH_OPS] as rOrd
LEFT JOIN (SELECT DISTINCT
[SPEC_NO]
,[SPEC_PART_NO]
,[MACH_NO]
,MACH_SEQ_NO
,[BLANK_WID]
,[BLANK_LEN]
,[NO_COLORS]
,[PRINTDIEID]
,[CUTDIEID]
,ROW_NUMBER() OVER (PARTITION BY MACH_NO ORDER BY MACH_SEQ_NO) as PASS_NO
FROM [CREATIVE].[dbo].[CTI_ROUTING_VIEW]) as rCti
ON rCti.SPEC_NO = rOrd.SPEC_NO
and rCti.MACH_NO =
CASE
WHEN rOrd.REPLACED_MACH_NO is null then rOrd.MACH_NO
ELSE rOrd.REPLACED_MACH_NO
END
and rCti.PASS_NO = rOrd.PASS_NO
LEFT JOIN INVENTORY_ITEM_TAB as rTab
ON rTab.SPEC_NO = rOrd.SPEC_NO
LEFT JOIN STYLE_DESCRIPTION as rStyle
ON rStyle.DESCR_CD = rTab.STYLE_CD
LEFT JOIN (
SELECT
JOB_NUMBER
,FORM_NO
,TRX_ORIG_MACH_NO
,PASS_NO
,SUM(GROSS_FG_QTY-WASTE_QTY) as NET_FG_SUM
,MAX(TRX_DATETIME) as MAX_TRX_DATETIME
FROM WIP_MACH_OPS
WHERE GROSS_FG_QTY <> 0
GROUP BY JOB_NUMBER, FORM_NO, TRX_ORIG_MACH_NO, PASS_NO) as rWip
ON rWip.JOB_NUMBER = rOrd.ORDER_NO
and rWip.FORM_NO = rOrd.ORDER_PART_NO
and rWip.TRX_ORIG_MACH_NO = rOrd.MACH_NO
and rWip.PASS_NO = rOrd.PASS_NO
WHERE rOrd.SCHED_START > DATEADD(DAY, -20, GETDATE())
I fixed it by adding a second partition.
ROW_NUMBER() OVER (PARTITION BY SPEC_NO, MACH_NO ORDER BY MACH_SEQ_NO) as PASS_NO

ROW_NUMBER count returns invalid result

I am quite new to SQL Server and trying to improve myself. I prepared a statement for fetching customers that are cancelled (where customerCancel is true)
Normally, when I count total number of cancelled customers, the total number is 1050.
What I want to do is to show first 100 users, but when I run the query below, I only get 38, when I increase RowNumber manually, the result is increasing but not being same with actual result. I will use this query for pagination.
My query:
SELECT
COUNT(*) OVER() TotalRowCount,
ID, customerNo, customerName, customerSurname, customerTitle, customerUnitList, customerTotalList
FROM
(SELECT
ROW_NUMBER() OVER(ORDER BY m.ID) RowNumber,
COUNT(*) OVER() TotalRowCount,
m.ID, m.customerNo, m.customerName, m.customerSurname, m.customerTitle,
(SELECT COUNT(f.ID)
FROM Invoices f
WHERE f.Paid = 0
AND f.custumerCancel = 0
AND f.customerID = m.ID) AS customerUnitList,
COALESCE((SELECT SUM(f.Total) AS InvoiceNo
FROM Invoices f
WHERE f.Paid = 0
AND f.custumerCancel = 0
AND f.customerID = m.ID), 0) AS customerTotalList
FROM
Customers m) flist
WHERE
customerTotalList > 0
AND RowNumber between 1 AND 100
I tried several way to fix it but no luck.
Try this query
SELECT * FROM (SELECT Count(*) OVER() TotalRowCount,
Row_number()
OVER(ORDER BY id) RowNumber,
id,
customerno,
customername,
customersurname,
customertitle,
customerunitlist,
customertotallist
FROM (SELECT m.id,
m.customerno,
m.customername,
m.customersurname,
m.customertitle,
(SELECT Count(f.id)
FROM invoices f
WHERE f.paid = 0
AND f.custumercancel = 0
AND f.customerid = m.id) AS
customerUnitList,
Isnull((SELECT Sum(f.total) AS InvoiceNo
FROM invoices f
WHERE f.paid = 0
AND f.custumercancel = 0
AND f.customerid = m.id), 0) AS
customerTotalList
FROM customers m) flist
WHERE customertotallist > 0) x
WHERE rownumber BETWEEN 1 AND 100
you are supposed to apply row number filter for paging, only after applying all your custom filters.
Using WHERE outside of the row_number() creating query means that some rows might be filtered by that. I bet that if you comment out the line before the last (customerTotalList>0) you will always get 100 rows.
If you want 100, you can just use
select top 100..........order by RowNumber asc
Which version of MS SQL Server do you have? This old approach was usable before to MS SQL Server 2012, from 2012 and up you have 0FFSET FETCH for pagination scenario.

How to add a count/sum and group by in a CTE

Just a question on displaying a row on flight level and displaying a count on how many crew members on that flight.
I want to change the output so it will only display a single record at flight level and it will display two additional columns. One column (cabincrew) is the count of crew members that have the 'CREWTYPE' = 'F' and the other column (cockpitcrew) is the count of crew members that have the `'CREWTYPE' = 'C'.
So the query result should look like:
Flight DepartureDate DepartureAirport CREWBASE CockpitCrew CabinCrew
LS361 2016-05-19 BFS BFS 0 3
Can I have a little help tweaking the below query please:
WITH CTE AS (
SELECT cd.*, c.*, l.Carrier, l.FlightNumber, l.Suffix, l.ScheduledDepartureDate, l.ScheduledDepartureAirport
FROM
(SELECT *, ROW_NUMBER() OVER(PARTITION BY LegKey ORDER BY UpdateID DESC) AS RowNumber FROM Data.Crew) c
INNER JOIN
Data.CrewDetail cd
ON c.UpdateID = cd.CrewUpdateID
AND cd.IsPassive = 0
AND RowNumber = 1
INNER JOIN
Data.Leg l
ON c.LegKey = l.LegKey
)
SELECT
sac.Airline + CAST(sac.FlightNumber AS VARCHAR) + sac.Suffix AS Flight
, sac.DepartureDate
, sac.DepartureAirport
, sac.CREWBASE
, sac.CREWTYPE
, sac.EMPNO
, sac.FIRSTNAME
, sac.LASTNAME
, sac.SEX
FROM
Staging.SabreAssignedCrew sac
LEFT JOIN CTE cte
ON sac.Airline + CAST(sac.FlightNumber AS VARCHAR) + sac.Suffix = cte.Carrier + CAST(cte.FlightNumber AS VARCHAR) + cte.Suffix
AND sac.DepartureDate = cte.ScheduledDepartureDate
PLEASE TRY THIS.
SELECT Flight,
DepartureDate,
DepartureAirport,
CREWBASE,
SUM(CASE WHEN CREWTYPE = 'F' THEN 1 ELSE 0 END) AS CabinCrew ,
SUM(CASE WHEN CREWTYPE = 'C' THEN 1 ELSE 0 END) AS CockpitCrew
FROM #Table
GROUP BY Flight, DepartureDate, DepartureAirport, CREWBASE
Please Try This:
select Flight, DepartureDate, DepartureAirport,CREWBASE,
count(case when CREWTYPE='F' then 1 end ) as CabinCrew,count(case when CREWTYPE='C' then 1 end ) as CockpitCrew
from Staging.SabreAssignedCrew
group by Flight, DepartureDate, DepartureAirport,CREWBASE