Odd GROUP BY output DB2 - Results not as expected - sql

If I run the following query:
select load_cyc_num
, crnt_dnlq_age_cde
, sum(cc_min_pymt_amt) as min_pymt
, sum(ec_tot_bal) as budget
, case when ec_tot_bal > 0 then 'Y' else 'N' end as budget
, case when ac_stat_cde in ('A0P','A1P','ARP','A3P') then 'Y' else 'N' end as arngmnt
, sum(sn_close_bal) as st_bal
from statements
where (sn_close_bal > 0 or ec_tot_bal > 0)
and load_cyc_num in (200911)
group by load_cyc_num
, crnt_dnlq_age_cde
, case when ec_tot_bal > 0 then 'Y' else 'N' end
, case when ac_stat_cde in ('A0P','A1P','ARP','A3P') then 'Y' else 'N' end
then I get the correct "BUDGET" grouping, but not the correct "ARRANGEMENT" grouping, only two rows have a "Y".
If I change the order of the case statements in the GROUP BY, then I get the correct grouping (full Y-N breakdown for both columns).
Am I missing something obvious?

Try moving
, sum(cc_min_pymt_amt) as min_pymt, sum(ec_tot_bal) as budget
to the end of the select statement, i.e.
select load_cyc_num,
crnt_dnlq_age_cde,
case when ec_tot_bal > 0 then 'Y' else 'N' end as budget,
case when ac_stat_cde in ('A0P','A1P','ARP','A3P') then 'Y' else 'N' end as arngmnt,
sum(sn_close_bal) as st_bal,
sum(cc_min_pymt_amt) as min_pymt,
sum(ec_tot_bal) as budget
from statements
where (sn_close_bal > 0 or ec_tot_bal > 0)and load_cyc_num in (200911)
group by load_cyc_num,
crnt_dnlq_age_cde,
case when ec_tot_bal > 0 then 'Y' else 'N' end ,
case when ac_stat_cde in ('A0P','A1P','ARP','A3P') then 'Y' else 'N' end

Related

Why does sum totals differ in query?

with totals as (select two_sim_ind,
case when account_type_key in(86,88,13,113,37,39,131) then 'B2C' else 'B2B' end as Segment,
case when subs_activation_date_key >= time_key then 'New' else 'Old' end as Sales_to_active,
time_key as TIME_KEY, name_region as REGION, area_name as DISTRICT, sim_type as USIM_FLAG,
case when lte_device = 1 or lte_ind in('Yes') or lte_user > 0 then '4G Device'
when ind_3g in('Yes') and lte_ind in('No') then '3G Device' else '2G Device' end as device_tech_support,
device_type as DEVICE_TYPE,
case when device_type in('Smartphone') then 'Yes' else 'No' end as is_Smartphone_AAB,
case when data_user in(0) then 'No' else 'Yes' end as is_Data_User,
case when lte_user in(0) then 'No' else 'Yes' end as is_4G_Data_User,
count(distinct subs_key) as A1M,
sum(total_revenue) as REVENUE_TOTAL,
sum(data_traffic_local_2g + data_traffic_local_3g+data_traffic_local_4g) as TRAFFIC_DATA_full_Sum,
sum(data_traffic_local_2g + data_traffic_local_3g) as g2_g3_traffic,
sum(data_traffic_local_4g) as Data_traffic_4g
from dwh.m as m
left join (select model_name, ind_3g, lte_ind
from dwh.w) as devices
on m.model_name = devices.model_name
where rtc_active_ind > 0 and subs_status_key in ('A', 'S')
and (time_key >= '2021-12-01' and time_key <= '2021-12-01')
group by two_sim_ind,
case when account_type_key in(86,88,13,113,37,39,131) then 'B2C' else 'B2B' end,
case when subs_activation_date_key >= time_key then 'New' else 'Old' end,
case when data_user in(0) then 'No' else 'Yes' end,
case when lte_device = 1 or lte_ind in('Yes') or lte_user > 0 then '4G Device'
when ind_3g in('Yes') and lte_ind in('No') then '3G Device' else '2G Device' end,
time_key, name_region, area_name, sim_type, device_type, lte_user)
select REGION, sum(REVENUE_TOTAL)
from totals
group by REGION
When I aggregate total of all records by region, value is significantly higher than it should be.
Result I get:
select name_region as REGION, sum(total_revenue)
from dwh.m
where (time_key >= '2021-12-01' and time_key <= '2021-12-01')
and rtc_active_ind > 0 and subs_status_key in ('A', 'S')
group by name_region;
Result of query and what I need:
Something happens to individual records when grouping by? What could be the reason?

IF ROWS IS ALL EQUAL

I want to use CASE WHEN Command, if my column IsApproved is all equal to 1 then the display is 'COMPLETE' then if there's still 0 then it is pending, depending on the ResignTxn number. How can I do that?
For example, if there's still 0 in txn number 45, then the output must be
pending, then if all the value is 1 then it must be complete.
Try below query:
select ResignTxn,
-- it counts 0 in particular ResignTxn
case when sum(case when isApproved = 0 then 1 else 0 end) > 0 then 'pending' else 'complete' end
from MyTable
group by ResignTxn
SELECT CASE WHEN MIN(IsApproved) =0 THEN 'Pending' ELSE 'Complete' END AS Status
FROM [Table]
Group by ResignTxn
Check min value
select ResignTxn , case min(IsApproved) when 1 then `COMPLETE' else 'pending' end
from mytable
group by ResignTxn
I personally would leave the logic out of the DB, just get the relevant data and evaluate it in your application, but you can do it like this if you want:
SELECT COUNT(*) AS countResult
WHERE IsApproved=0,
CASE
WHEN countResult > 0 THEN "PENDING"
ELSE "COMPLETE"
END AS ResultText
FROM myTable;
You may use:
select case when IsApproved = 1 then 'Complete' else 'Pending' end as Status
from YOURTABLE

SQL Query to Combine rows

I have a query that currently prints out what I need but doesn't combine the rows that I need. For example, I need the first two rows with the meter name to be combined together and so on for the rest of the meter names.
This is currently what I have:
SELECT
--Displays Client Number
CASE
WHEN v.MID IS NULL THEN ''
ELSE v.ClientNumber
END AS 'Client Number',
--Displays MID Number
CASE
WHEN v.MID IS NULL THEN ''
ELSE v.MID
END AS MID,
--Displays Meter Name
CASE
WHEN v.MID IS NULL THEN ''
ELSE v.MeterName
END AS 'Meter Name',
/*
CASE
WHEN v.MID IS NULL THEN 0
ELSE SUM(v.MCF)
END AS MCF,
*/
--Displays January's MCF
CASE
WHEN v.AccountPeriod = '2018-01-01' THEN SUM(v.MCF)
ELSE 0
END AS January,
--Displays Febuary's MCF
CASE
WHEN v.AccountPeriod = '2018-02-01' THEN SUM(v.MCF)
ELSE 0
END AS Febuary,
CASE
WHEN v.MID IS NULL THEN 0
ELSE SUM(v.mcf)
END AS 'Meter Total'
FROM Volumes v
LEFT JOIN CurrentMeters cm
ON v.MID = cm.MID
WHERE cm.ClientNumber = 107500
GROUP BY v.MID, v.AccountPeriod, v.ClientNumber, v
Does anyone have any suggestions as to what I should do or how I should approach this?
I think you just want conditional aggregation:
SELECT (CASE WHEN v.MID IS NULL THEN '' ELSE v.ClientNumber END) AS Client_Number,
COALESCE(WHEN v.MID, '') as MID,
(CASE WHEN v.MID IS NULL THEN '' ELSE v.MeterName END) AS Meter_Name,
SUM((CASE WHEN v.MID IS NULL THEN 0 v.MCF END) AS MCF,
SUM(CASE WHEN v.AccountPeriod = '2018-01-01' THEN v.MCF ELSE 0 END) AS January,
SUM(CASE WHEN v.AccountPeriod = '2018-02-01' THEN v.MCF ELSE 0 END) AS January,
SUM(CASE WHEN v.MID IS NULL THEN 0 ELSE v.mcf END) AS Meter_Total
FROM Volumes v JOIN
CurrentMeters cm
ON v.MID = cm.MID
WHERE cm.ClientNumber = 107500
GROUP BY (CASE WHEN v.MID IS NULL THEN '' ELSE v.ClientNumber END),
COALESCE(WHEN v.MID, ''),
(CASE WHEN v.MID IS NULL THEN '' ELSE v.MeterName END);
Notes:
Your WHERE clause is turning the outer join into an inner join, so there is no reason to express an outer join.
The GROUP BY keys specify what defines a row in the result set. Each combination of unique values in the data is in exactly one row. Hence, you don't want AccountPeriod in the GROUP BY.
Presumably, you want one row for each of the expressions that define a row, so these expressions are in the group by.
For conditional aggregation, the CASE expression is an argument to an aggregation function such as SUM().

Avoiding a divide by zero error in a case statement

I am getting a divide by zero error in my script.
Can anyone please help.
I am trying to divide two records and one of them has zero in it. I dont want to lose the row, please advise.
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) as "Paid in 24hrs",
COUNT([MONTH_OF_SUSPENSION])/sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) as "Achieved"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
You can introduce a second case to check the result of the sum:
case
when sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) > 0
then COUNT([MONTH_OF_SUSPENSION])/sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end)
else 0 /* a default value that makes sense to you */
end as "Achieved"
Looking at your code I could assume you are using MSSQL and therefore you could use nullif which returns null if two arguments are equal. So for example your code could look like :
COUNT([MONTH_OF_SUSPENSION])/nullif(sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end),0) as "Achieved"
What it does is if the value of the sum operator is equal 0 then the divisor is turn from zero into null and that will result in the entire equation to become null.
use another case statement to check the result of your sum
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "Paid in 24hrs",
case
when sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) = 0 then 'whatever you want in this case'
else COUNT([MONTH_OF_SUSPENSION])/sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "Achieved"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
although this is pretty nasty looking, so you could tidy it up a bit with a sub-select:
select
year,
month,
request,
PaidIn24hrs,
case
when PaidIn24hrs = 0 then 'whatever you want in this case'
else request/PaidIn24hrs
end as "Achieved"
from
(
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "PaidIn24hrs"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
)

can not pivot table sql

i want to pivot table but i get some error about this image
this is my code
SELECT ARCBG_Abbrev
,ARCIM_Code
,SUM(CASE WHEN TAR_Code = 'O' THEN ITP_Price
ELSE 0 END) AS O
,SUM(CASE WHEN TAR_Code = 'I' THEN ITP_Price ELSE 0 END)
AS I
,SUM(CASE WHEN TAR_Code = 'F' THEN ITP_Price ELSE 0 END)
AS F
FROM SYSTEM.VS_OrderItem
WHERE (ARCIM_Code = '010004')
GROUP BY ARCBG_Abbrev, ARCIM_Code
i try to distinct column to check value in column is same in every row where ARCIM_Code = 010004 .it's the same value in column ARCBG_Abbrev. Can you check my pivot code plascc. thank you
on the assumption it's an ODBC driver limitation, perhaps nesting the case expressions as a subquery will help.
SELECT
ARCBG_Abbrev
, ARCIM_Code
, SUM(O) AS O
, SUM(I) AS I
, SUM(F) AS F
FROM (
SELECT
ARCBG_Abbrev
, ARCIM_Code
, CASE
WHEN TAR_Code = 'O' THEN
ITP_Price
ELSE
0
END AS O
, CASE
WHEN TAR_Code = 'I' THEN
ITP_Price
ELSE
0
END AS I
, CASE
WHEN TAR_Code = 'F' THEN
ITP_Price
ELSE
0
END AS F
FROM SYSTEM.VS_OrderItem
) AS SQ
WHERE ARCIM_Code = '010004'
GROUP BY
ARCBG_Abbrev
, ARCIM_Code