Count, Having and Case statement - sql

I'm looking to produce a count of projects based on 3 different conditions (DB2 database). I need to count all projects <= .10, >= .5, and >= 1.00 (percentage_used) but can only group by dim_building_id and building_name. Of course this query will not run because it requires percentage_used to be added to the group by. How do I handle those 3 conditions with percentage_used?
SELECT
SUM(CAST(FTS.GROUP_A AS BIGINT)) AS GROUP_A,
SUM(CAST(FTS.GROUP_B AS BIGINT)) AS GROUP_B,
SUM(CAST(FTS.GROUP_C AS BIGINT)) AS GROUP_C,
CASE WHEN FAT.PERCENTAGE_USED <= '0.10'
THEN COUNT(*)
END AS PROJECTS_L10,
CASE WHEN FAT.PERCENTAGE_USED >= '0.50'
THEN COUNT(*)
END AS PROJECTS_G50,
CASE WHEN FAT.PERCENTAGE_USED >= '1.00'
THEN COUNT(*)
END AS PROJECTS_G100,
DAYS(DATE('2014-07-01')) - DAYS(CURRENT DATE) AS DAYS_LEFT,
(DAYS(DATE('2014-07-01')) - DAYS(CURRENT DATE))/7 AS WEEKS_LEFT,
DAYS(DATE('2013-12-31')) - DAYS(CURRENT DATE) AS DAYS_LEFT_YEAR
FROM FACT_TABLE AS FAT
INNER JOIN GROUPS AS FTS ON FAT.DIM_PROJECT_ID = FTS.DIM_PROJECT_ID
GROUP BY FAT.DIM_BUILDING_ID, FAT.BUILDING_NAME;

I'd do something like this:
select bn.building_name ,
t.*
from ( select fat.building_id ,
sum( case when fat.percentage_used <= 0.10 then 1 else 0 end ) as group_a ,
sum( case when fat.percentage_used > 0.10 and fat.percentage_used < 0.50 then 1 else 0 end ) as group_b ,
sum( case when fat.percentage_used >= 0.50 and fat.percentage_used < 1.00 then 1 else 0 end ) as group_c ,
sum( case when fat.percentage_used >= 1.00 then 1 else 0 end ) as group_d ,
sum( case when fat.percentage_used is null then 1 else 0 end ) as group_e
from fact_table fat
join groups fts on tfs.dim_project_id = fat.dim_project_id
group by fat.building_id
) t
join fact_table bn on bn.building_id = t.building_id

Instead of putting the aggregate as the THEN, wrap the CASE statement in an aggregate:
SELECT
SUM(CAST(FTS.GROUP_A AS BIGINT)) AS GROUP_A,
SUM(CAST(FTS.GROUP_B AS BIGINT)) AS GROUP_B,
SUM(CAST(FTS.GROUP_C AS BIGINT)) AS GROUP_C,
SUM(CASE WHEN FAT.PERCENTAGE_USED <= '0.10' THEN 1 ELSE 0 END) AS PROJECTS_L10,
SUM(CASE WHEN FAT.PERCENTAGE_USED >= '0.50' THEN 1 ELSE 0 END) AS PROJECTS_G50,
SUM(CASE WHEN FAT.PERCENTAGE_USED >= '1.00' THEN 1 ELSE 0 END) AS PROJECTS_G100,
DAYS(DATE('2014-07-01')) - DAYS(CURRENT DATE) AS DAYS_LEFT,
(DAYS(DATE('2014-07-01')) - DAYS(CURRENT DATE))/7 AS WEEKS_LEFT,
DAYS(DATE('2013-12-31')) - DAYS(CURRENT DATE) AS DAYS_LEFT_YEAR
FROM FACT_TABLE AS FAT
INNER JOIN GROUPS AS FTS ON FAT.DIM_PROJECT_ID = FTS.DIM_PROJECT_ID
GROUP BY FAT.DIM_BUILDING_ID, FAT.BUILDING_NAME;
The ELSE 0 isn't needed, but some like to see it in the query.
Alternatively this should work as well:
COUNT(CASE WHEN FAT.PERCENTAGE_USED >= '0.50' THEN 1 END) AS PROJECTS_G50,

Related

How to split data in SQL

I have the following code:
select
FeeEarnerID,
(
select
(select [name] from [User] AS u where u.userid=f.userid)
from
feeearner AS f
where
f.FeeEarnerID=aa.FeeEarnerID
) FeeEarner,
sum(aa.FEES) Fees,
sum(aa.DISB) Disbursements,
sum(aa.CREDITORS) Creditors
from
(
SELECT
FeeEarner.FeeEarnerID,
case when WIPTransaction.WIPTransactionTypeID IN (1,17,18,20,21,25) then WIPTransaction.Amount else 0 end 'FEES',
case when WIPTransaction.WIPTransactionTypeID IN (2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,26,27,28,29) then WIPTransaction.Amount else 0 end 'DISB',
case when WIPTransaction.WIPTransactionTypeID IN (24) then WIPTransaction.Amount else 0 end 'CREDITORS'
FROM
(
(
FeeEarner
JOIN
WIPTransaction ON FeeEarner.FeeEarnerID = WIPTransaction.FeeEarnerID
)
JOIN
WIPTransactionType ON WIPTransactionType.WIPTransactionTypeID = WIPTransaction.WIPTransactionTypeID
)
WHERE
(WIPTransaction.TransactionDate BETWEEN '2020-10-01' AND '2020-12-31')
)
AS aa
group by
FeeEarnerID
Used Table names: WIPtransaction, WIPtransactiontype, Feeearner
I want to display two more columns at the end of the output, namely: Invoiced and Uninvoiced.
The "Invoicenumber" field in the "WIPtransaction" database will be tested for this. If the "Invoicenumber" is NULL - the transaction amount will be added to a sum in the uninvoiced column and if "Invoicenumber" contains a number - the transaction amount will be added to a sum in the invoiced column.
What is the code that I would need to write and where would it be placed?
select
FeeEarnerID,
(
select
(select [name] from [User] AS u where u.userid=f.userid)
from
feeearner AS f
where
f.FeeEarnerID=aa.FeeEarnerID
) FeeEarner,
sum(aa.FEES) Fees,
sum(aa.DISB) Disbursements,
sum(aa.CREDITORS) Creditors,
----------
SUM( InvoicedAmount) AS InvoicedAmount,
SUM(UnInvoicedAmount) AS UnInvoicedAmount
----------
from
(
SELECT
FeeEarner.FeeEarnerID,
case when WIPTransaction.WIPTransactionTypeID IN (1,17,18,20,21,25) then WIPTransaction.Amount else 0 end 'FEES',
case when WIPTransaction.WIPTransactionTypeID IN (2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,26,27,28,29) then WIPTransaction.Amount else 0 end 'DISB',
case when WIPTransaction.WIPTransactionTypeID IN (24) then WIPTransaction.Amount else 0 end 'CREDITORS',
----------
CASE WHEN WIPTransaction.Invoicenumber IS NOT NULL THEN WIPTransaction.Amount END AS InvoicedAmount,
CASE WHEN WIPTransaction.Invoicenumber IS NULL THEN WIPTransaction.Amount END AS UnInvoicedAmount
----------
FROM
FeeEarner
JOIN
WIPTransaction ON FeeEarner.FeeEarnerID = WIPTransaction.FeeEarnerID
JOIN
WIPTransactionType ON WIPTransactionType.WIPTransactionTypeID = WIPTransaction.WIPTransactionTypeID
WHERE
WIPTransaction.TransactionDate BETWEEN '2020-10-01' AND '2020-12-31'
)
AS aa
group by
FeeEarnerID
You can remove your derived query and combine it all into one. The FeeEarner double sub-query can also be optimized:
select
FeeEarnerID,
(
select [name] from [User] AS u where u.userid=FeeEarner.userid
) FeeEarner,
sum(case when WIPTransaction.WIPTransactionTypeID IN (1,17,18,20,21,25) then WIPTransaction.Amount else 0 end) Fees,
sum(case when WIPTransaction.WIPTransactionTypeID IN (2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,26,27,28,29) then WIPTransaction.Amount else 0 end) Disbursements,
sum(case when WIPTransaction.WIPTransactionTypeID IN (24) then WIPTransaction.Amount else 0 end) Creditors,
SUM(CASE WHEN WIPTransaction.Invoicenumber IS NOT NULL THEN WIPTransaction.Amount END) AS InvoicedAmount,
SUM(CASE WHEN WIPTransaction.Invoicenumber IS NULL THEN WIPTransaction.Amount END) AS UnInvoicedAmount
FROM
FeeEarner
JOIN
WIPTransaction ON FeeEarner.FeeEarnerID = WIPTransaction.FeeEarnerID
JOIN
WIPTransactionType ON WIPTransactionType.WIPTransactionTypeID = WIPTransaction.WIPTransactionTypeID
WHERE
WIPTransaction.TransactionDate BETWEEN '2020-10-01' AND '2020-12-31'
group by
FeeEarnerID;

how to do math function (divide) for results of a group by function

I have a table of 6 digit event numbers;
i am trying to count one event number (let's say 600189) that has occurred during a specific time period, and divide it by a count of a second event number (lets say 600122) during the same time period.
the below query gets my two counts but I want to modify the query to do the calculation (count of 600189 / count of 600122) * 100 :
select count (messageno)
from event
where timestamp > '2019-03-14' and timestamp < '2019-03-15' and
messageno in ('600122','600189')
group by messageno
I would simply use conditional aggregation:
select sum(case when messageno = '600122' then 1 else 0 end) as cnt_1,
sum(case when messageno = '600189' then 1 end) as cnt_2,
( sum(case when messageno = '600122' then 1 else 0 end) /
sum(case when messageno = '600189' then 1 end)
) as ratio
from event
where timestamp > '2019-03-14' and
timestamp < '2019-03-15' and
messageno in ('600122', '600189');
Note that the else in the denominator is removed. This is intentional. If there are no messages with that number, then this returns NULL instead of a divide-by-zero error.
There are a couple of query patterns.
One approach is conditional aggregation. We can return a value of 1 if a condition is true, otherwise return 0, and add up the 1s and 0s with a SUM aggregate to get a count. Consider:
For MySQL, we can do something like this:
SELECT SUM( IF(e.messageno='600122',1,0) ) AS cnt_600122
, SUM( IF(e.messageno='600189',1,0) ) AS cnt_600189
, ( 100.0
* SUM( IF(e.messageno='600122',1,0) )
/ SUM( IF(e.messageno='600189',1,0) )
) AS pct
FROM event e
WHERE e.timestamp > '2019-03-14'
AND e.timestamp < '2019-03-15'
AND e.messageno IN ('600122','600189')
More portable ANSI standards compliant equivalent will work for Microsoft SQL Server et al.:
SELECT SUM( CASE e.messageno WHEN '600122' THEN 1 ELSE 0 END ) AS cnt_600122
, SUM( CASE e.messageno WHEN '600189' THEN 1 ELSE 0 END ) AS cnt_600189
, ( 100.0
* SUM( CASE e.messageno WHEN '600122' THEN 1 ELSE 0 END )
/ SUM( CASE e.messageno WHEN '600122' THEN 1 ELSE 0 END )
) AS pct
FROM event e
WHERE e.timestamp > '2019-03-14'
AND e.timestamp < '2019-03-15'
AND e.messageno IN ('600122','600189')
Other approaches would be to do aggregation in an inline view(s), or use subqueries in the SELECT list:
SELECT 100.0
* ( SELECT SUM(1)
FROM event e
WHERE e.timestamp > '2019-03-14'
AND e.timestamp < '2019-03-15'
AND e.messageno IN ('600122')
)
/ ( SELECT SUM(1)
FROM event e
WHERE e.timestamp > '2019-03-14'
AND e.timestamp < '2019-03-15'
AND e.messageno IN ('600189')
)
AS pct

SSRS: how to get top 3 in order Z to A

I try to get in my diagram the top 3 of the worst value in SSRS:
my Code:
SELECT *
FROM (
Select top 3
intervaldate as Datum
,Name
,teamname as Team
,SUM(case when CounterName = 'Blown away' then calculationUnits else 0 end) as Blown
,Sum(case when CounterName = 'Thrown away' then calculationUnits else 0 end) as Thrown
,Sum(case when CounterName = 'total' then calculationUnits else 0 end) as Total
from Counting
where IntervalDate >= dateadd(day,datediff(day,1,GETDATE()),0)
AND IntervalDate < dateadd(day,datediff(day,0,GETDATE()),0)
and Name in (Select SystemID from tSystemView where SystemViewID = 2)
group by intervaldate, teamName, Name
) c
Expression of the diagram:
=Sum(Fields!Blown.Value + Fields!Thrown.Value) / Sum(Fields!Total.Value) * 100
And I sorted it from highest to lowest
But it does not show me the right order.
If I choose every "Name" then it shows me other value then the top 3:
all Names with value:
top 3:
It's because your top 3 statement is in the SQL while your sort is in the report. Without an order by SQL picks the top 3 random records. Also, unless there is more SQL you are not showing, the outer select is unnecessary. Add an order by <column> desc below your group by.
with Calcs as
(
select intervaldate as Datum,
Name,
TeamName,
SUM(case when CounterName = 'Blown away' then calculationUnits else 0 end) as Blown,
Sum(case when CounterName = 'Thrown away' then calculationUnits else 0 end) as Thrown,
Sum(case when CounterName = 'total' then calculationUnits else 0 end) as Total
from Counting
where IntervalDate >= dateadd(day,datediff(day,1,GETDATE()),0)
AND IntervalDate < dateadd(day,datediff(day,0,GETDATE()),0)
and Name in (Select SystemID from tSystemView where SystemViewID = 2)
group by intervaldate, teamName, Name
)
select b.*
from
(
select a.*, row_number() over (order by (Blown + Thrown)/Total desc) as R_Ord -- Change between ASC/DESC depending on needs
from Calcs a
) b
where R_Ord <=3

Revenue for two months date wise

I am trying to get data for last 2 month ...but the query does not give perfect result....
SELECT DAY(table_A.PaymentDate) as date1 ,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP) - 1
then CAST(SUM(table_A.Total_Amount) AS INT)
else 0
end) AS last_month_CNT,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP)
then CAST(SUM(table_A.Total_Amount) As INT)
else 0
end) as This_month_CNT
FROM Tbl_Pan_Paymentdetails table_A
FULL OUTER JOIN Tbl_Pan_Paymentdetails table_B
ON table_A.PaymentDate=table_B.PaymentDate
WHERE YEAR(table_A.PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND
table_A.PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY
DAY(table_A.PaymentDate) ,MONTH(table_A.PaymentDate)
order by
DAY(table_A.PaymentDate);
Move the entire case expression inside the sum function and don't include the month in the group by. Also, the full outer join seems unnecessary so I removed it.
This should be what you are looking for:
SELECT
DAY(PaymentDate) as date1 ,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP)-1 THEN CAST(Total_Amount AS INT) ELSE 0 END) AS last_month_CNT,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP) THEN CAST(Total_Amount AS INT) ELSE 0 END) AS This_month_CNT
FROM Tbl_Pan_Paymentdetails
WHERE YEAR(PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY DAY(PaymentDate)
ORDER BY DAY(PaymentDate);

SQL group join table

Hi I want to display out the record in the format as below. How to I display the format as below ?
Branch Total Payment Total Discount Total Net Payment
A 10,000 2,000 8,000
B 29,190 1,540 27,656
Here are my query for the above. Please help me. Thanks.
SELECT TranID, ProjCode,
CASE WHEN IsActive='N' THEN 'Cancellation' ELSE PaymentType END As PaymentType,
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Sale END) END As Sale ,
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Sale_Before_CutOff END) END As Sale_Before_CutOff ,
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Net END) END As Net ,
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Net_Before_CutOff END) END As Net_Before_CutOff ,
CASE WHEN PaymentType='Withdrawal' THEN Net ELSE 0 END As Withdrawal,
CASE WHEN PaymentType='Withdrawal' THEN Net_Before_CutOff ELSE 0 END As Withdrawal_Before_CutOff,
CASE WHEN IsActive='N' THEN Net ELSE 0 END As Cancellation,
CASE WHEN IsActive='N' THEN Net_Before_CutOff ELSE 0 END As Cancellation_Before_CutOff,
CASE WHEN IsActive='N' THEN 0 ELSE Discount END As Discount,
CASE WHEN IsActive='N' THEN 0 ELSE Discount_Before_CutOff END As Discount_Before_CutOff, AdditionalCommission,AdditionalCommission_Before_CutOff, Remark, UserStamp, BusinessDay,
TranDate, BranchID, StaffCode, IsActive,Quantity
FROM
(SELECT c.INTERNAL_TRAN_NUM AS TranID, c.PROJECT_CODE AS ProjCode, c.PAYMENT_TYPE AS PaymentType,d.QUANTITY As Quantity,
CASE WHEN DATEPART(hh,c.TRAN_DATE) > DATEPART(hh, f.CUT_OFF_TIME) THEN c.TOTAL_PAYMENT ELSE 0 END AS Sale,
CASE WHEN DATEPART(hh, c.TRAN_DATE)<= DATEPART(hh, f.CUT_OFF_TIME) THEN c.TOTAL_PAYMENT ELSE 0 END AS Sale_Before_CutOff,
CASE WHEN DATEPART(hh, c.TRAN_DATE)> DATEPART(hh, f.CUT_OFF_TIME) THEN c.NET_PAYMENT ELSE 0 END AS Net,
CASE WHEN DATEPART(hh, c.TRAN_DATE) <= DATEPART(hh,f.CUT_OFF_TIME) THEN c.NET_PAYMENT ELSE 0 END AS Net_Before_CutOff,
CASE WHEN DATEPART(hh, c.TRAN_DATE) > DATEPART(hh,f.CUT_OFF_TIME) THEN c.DISCOUNT_AMOUNT ELSE 0 END AS Discount,
CASE WHEN DATEPART(hh, c.TRAN_DATE) <= DATEPART(hh,f.CUT_OFF_TIME) THEN c.DISCOUNT_AMOUNT ELSE 0 END AS Discount_Before_CutOff,
CASE WHEN DATEPART(hh, c.TRAN_DATE) > DATEPART(hh, f.CUT_OFF_TIME) THEN d.USER_DEF8 ELSE 0 END As AdditionalCommission,
CASE WHEN DATEPART(hh, c.TRAN_DATE) <= DATEPART(hh, f.CUT_OFF_TIME) THEN d.USER_DEF8 ELSE 0 END As AdditionalCommission_Before_CutOff,
c.REMARKS AS Remark, c.USER_STAMP AS UserStamp,CAST(DATEADD(hh, - DATEPART(hh, f.CUT_OFF_TIME), c.TRAN_DATE) AS DATE) AS BusinessDay,
c.TRAN_DATE AS TranDate, e.BRANCH_ID AS BranchID, d.STAFF_CODE AS StaffCode, c.ISACTIVE AS IsActive
FROM SC_TRAN_HEADER AS c
INNER JOIN SC_TRAN_DETAIL AS d ON d.INTERNAL_TRAN_NUM = c.INTERNAL_TRAN_NUM
INNER JOIN SC_BRANCH AS e ON c.BRANCH_NUM = e.INTERNAL_NUM
INNER JOIN SC_COMMISSION AS f ON f.BRANCH_NUM = c.BRANCH_NUM) AS TMP
The best that I can come up with, based on the information in your question, is:
with cte as (<your query here>)
select branchid, sum(sale) as payment, sum(discount) as discount,
sum(sale) - sum(discount)
from cte
group by branchid;
If this is not correct, then edit your question to provide more information to help resolve your question.
FIRST, I would try to simplify the readability of this query from all the case/when conditions. First, you do case/when in your preliminary query on repeated tests to get before and after cut-off period, then others you do based on withdrawal or NOT withdrawal and yet again for Active vs Not Active.
Simple math multipliers... consider your query segment... your inner query to get the values of Sale and Sale_Before_CutOff.
CASE WHEN DATEPART(hh,c.TRAN_DATE) > DATEPART(hh, f.CUT_OFF_TIME) THEN c.TOTAL_PAYMENT ELSE 0 END AS Sale,
CASE WHEN DATEPART(hh, c.TRAN_DATE)<= DATEPART(hh, f.CUT_OFF_TIME) THEN c.TOTAL_PAYMENT ELSE 0 END AS Sale_Before_CutOff,
Both test the date part for the cutoff time, and the answer can be Before, or After, never both. You do the same tests for Net, Net_Before_Cutoff, Withdrawal, Withdrawal_Before_Cutoff.
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Net END) END As Net ,
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Net_Before_CutOff END) END As Net_Before_CutOff ,
CASE WHEN PaymentType='Withdrawal' THEN Net ELSE 0 END As Withdrawal,
CASE WHEN PaymentType='Withdrawal' THEN Net_Before_CutOff ELSE 0 END As Withdrawal_Before_CutOff,
THEN, in your main part of the query, you are applying yet again a nested case/when(case/when)
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Sale END) END As Sale ,
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Sale_Before_CutOff END) END As Sale_Before_CutOff ,
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Net END) END As Net ,
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Net_Before_CutOff END) END As Net_Before_CutOff ,
CASE WHEN PaymentType='Withdrawal' THEN Net ELSE 0 END As Withdrawal,
CASE WHEN PaymentType='Withdrawal' THEN Net_Before_CutOff ELSE 0 END As Withdrawal_Before_CutOff,
What I would do, is from your subquery qualifying records, I would get the raw amount columns and 6 flags to act as multiplers.
SELECT ...
c.TOTAL_PAYMENT,
c.Net_Payment,
c.Discount_Amount,
CASE WHEN DATEPART(hh,c.TRAN_DATE) > DATEPART(hh, f.CUT_OFF_TIME)
THEN 1 ELSE 0 END as AfterMult,
CASE WHEN DATEPART(hh,c.TRAN_DATE) > DATEPART(hh, f.CUT_OFF_TIME)
THEN 0 ELSE 1 END as BeforeMult,
CASE WHEN c.PaymentType='Withdrawal'
THEN 1 ELSE 0 END as WithdrawalMult,
CASE WHEN c.PaymentType='Withdrawal'
THEN 0 ELSE 1 END as NotAWithdrawalMult,
CASE WHEN c.IsActive='N'
THEN 1 ELSE 0 END As NotActiveMult,
CASE WHEN c.IsActive='N'
THEN 0 ELSE 1 END As ActiveMult, ...
Notice, the same condition is applied to both parts, only the THEN/ELSE swaps the multiplier from a 1 to 0 respectively to what it should represent. So, for any given record, example result would be
Total_Payment Net_Payment Discount_Amount AfterMult BeforeMult WithdrawalMult NotAWithdrawalMult NotActiveMult ActiveMult
100 86 14 1 0 1 0 0 1
200 170 30 0 1 0 1 1 0
Now, simple thoughts... if you want to know how much total payments were before a cutoff and were NOT withdrawls, in your upper query it would be
Total_Payment * BeforeMult * NotAWithdrawal = TotalPayments_BeforeCutoff
vs payments AFTER cutoff
Total_Payment * AfterMult * NotAWithdrawal = TotalPayments_BeforeCutoff
Similar consideration for your Active vs Not active. Use that multiplier, no sense in doing nested cases when you already have determined its status when pulling the records. Lets take a look at your "Sale" column... The inner query getting the record is using the "Total_Payment" field
CASE WHEN DATEPART(hh,c.TRAN_DATE) > DATEPART(hh, f.CUT_OFF_TIME) THEN c.TOTAL_PAYMENT ELSE 0 END AS Sale,
then in the upper is a nested case/when.
CASE WHEN PaymentType='Withdrawal' THEN 0 ELSE (CASE WHEN IsActive='N' THEN 0 ELSE Sale END) END As Sale ,
The only time you care about the sale amount is when it is AFTER the cutoff, is NOT a withdrawal and when it IS Active, so just multiply those flags
Total_Payment * AfterMult * NotAWithdrawalMult * ActiveMult as Sale
Total_Payment * BeforeMult * NotAWithdrawalMult * ActiveMult as Sale_Before_Cutoff
Finally, you have so many other columns in the table being pulled and not used, why keep them. And for what you are trying to get the SUM() of, its going to be much easier to read it something like
SUM( Total_Payment * AfterMult * NotAWithdrawalMult * ActiveMult ) as TotalSale
SUM( Total_Payment * BeforeMult * NotAWithdrawalMult * ActiveMult ) as TotalSale_Before_Cutoff
All that being said, I offer you this... please confirm context, but should make sense from above. Also, note, the last 3 column I added were the final total you are probably looking for where the summation did not care as to before or after the time cutoff... just the fact it was a valid payment/discount/net, was Active, and on two of them was NOT a withdrawal... Seeing this, you would need to confirm its accuracy. The first 6 summations show based on respective after cutoff (no column name suffix) vs BEFORE the cutoff (column name HAS the suffix)
SELECT
PQ.Branch_Name, <-- CONFIRM COLUMN FROM PreQuery (PQ alias)
SUM( PQ.Total_Payment * PQ.AfterMult * PQ.NotAWithdrawalMult * PQ.ActiveMult ) as TotalSale,
SUM( PQ.Total_Payment * PQ.BeforeMult * PQ.NotAWithdrawalMult * PQ.ActiveMult ) as TotalSale_BeforeCutoff,
SUM( PQ.Discount_Amount * PQ.AfterMult * PQ.ActiveMult ) as TotalDiscount,
SUM( PQ.Discount_Amount * PQ.BeforeMult * PQ.ActiveMult ) as TotalDiscount_BeforeCutoff,
SUM( PQ.Net_Payment * PQ.AfterMult * PQ.NotAWithdrawalMult * PQ.ActiveMult ) as Net,
SUM( PQ.Net_Payment * PQ.BeforeMult * PQ.NotAWithdrawalMult * PQ.ActiveMult ) as Net_BeforeCutoff,
SUM( PQ.Total_Payment * PQ.NotAWithdrawalMult * PQ.ActiveMult ) as TotalSaleAll,
SUM( PQ.Discount_Amount * PQ.ActiveMult ) as TotalDiscountAll,
SUM( PQ.Net_Payment * PQ.NotAWithdrawalMult * PQ.ActiveMult ) as NetAll
from
( select
e.Branch_Name, <-- GUESSING ON THIS COLUMN FOR ACTUAL BRANCH
c.Total_Payment,
c.Net_Payment,
c.Discount_Amount,
CASE WHEN DATEPART(hh,c.TRAN_DATE) > DATEPART(hh, f.CUT_OFF_TIME)
THEN 1 ELSE 0 END as AfterMult,
CASE WHEN DATEPART(hh,c.TRAN_DATE) > DATEPART(hh, f.CUT_OFF_TIME)
THEN 0 ELSE 1 END as BeforeMult,
CASE WHEN c.PaymentType='Withdrawal'
THEN 1 ELSE 0 END as WithdrawalMult,
CASE WHEN c.PaymentType='Withdrawal'
THEN 0 ELSE 1 END as NotAWithdrawalMult,
CASE WHEN c.IsActive='N'
THEN 1 ELSE 0 END As NotActiveMult,
CASE WHEN c.IsActive='N'
THEN 0 ELSE 1 END As ActiveMult
FROM
SC_TRAN_HEADER AS c
INNER JOIN SC_TRAN_DETAIL AS d
ON c.INTERNAL_TRAN_NUM = d.INTERNAL_TRAN_NUM
INNER JOIN SC_BRANCH AS e
ON c.BRANCH_NUM = e.INTERNAL_NUM
INNER JOIN SC_COMMISSION AS f
ON c.BRANCH_NUM = f.BRANCH_NUM ) AS PQ
group by
PQ.Branch_Name <-- AGAIN, confirm column name here