SQL Case - grouping values returned by ELSE - sql

How can I receive only one row for category "Other" with a total of 111?

Wrap the CASE query up in a derived table, GROUP BY its result.
select "Channel", count(*) AS "Orders per Channel"
from
(
SELECT CASE hhhogcl
WHEN 'P' THEN 'One Step'
WHEN 'O' THEN 'Customer Service'
WHEN 'R' THEN 'Remote FTP'
WHEN 'N' THEN 'PowerNet'
WHEN 'S' THEN 'PowerSell'
WHEN 'M' THEN 'PowerMobile'
ELSE 'Other'
END AS "Channel",
FROM s2151bdw.pwrdta.ffdcstbp
JOIN s2151bdw.pwrdta.hhhordhl0
ON hhhcusn = ffdcusn
WHERE hhhcmpn = 1
AND hhhdivn = 1
AND hhhdptn = 1
AND hhhdtes > 0 --Ship Date AND HHHDTES BETWEEN 20180611 AND 20180611
) dt
GROUP BY "Channel"
ANSI SQL compliant!

You should GROUP BY CASE expression instead of HHHOGCL:
SELECT CASE hhhogcl
WHEN 'P' THEN 'One Step'
WHEN 'O' THEN 'Customer Service'
WHEN 'R' THEN 'Remote FTP'
WHEN 'N' THEN 'PowerNet'
WHEN 'S' THEN 'PowerSell'
WHEN 'M' THEN 'PowerMobile'
ELSE 'Other'
END AS "Channel",
Count(*) AS "Orders per Channel"
FROM s2151bdw.pwrdta.ffdcstbp
JOIN s2151bdw.pwrdta.hhhordhl0
ON hhhcusn = ffdcusn
WHERE hhhcmpn = 1
AND hhhdivn = 1
AND hhhdptn = 1
AND hhhdtes > 0 --Ship Date AND HHHDTES BETWEEN 20180611 AND 20180611
GROUP BY
CASE hhhogcl
WHEN 'P' THEN 'One Step'
WHEN 'O' THEN 'Customer Service'
WHEN 'R' THEN 'Remote FTP'
WHEN 'N' THEN 'PowerNet'
WHEN 'S' THEN 'PowerSell'
WHEN 'M' THEN 'PowerMobile'
ELSE 'Other'
END

Related

Nested CASE statements in SQL

I am running the below SQL and I need to add a case statement for the svcState column.
I have a value defined for each number in that column which I need to have in my query. For instance 7 is OK, 4 is down etc. I tried adding this in the CASE statement as below and it seems, the syntax is incorrect. Any help will be greatly appreciated.
SELECT * FROM
(
SELECT
A.NodeName AS NodeName,
MAX(CASE WHEN Poller_Name='svcServiceName' THEN CAST(Status AS varchar) ELSE ''END) svcServiceName,
MAX(CASE (CASE WHEN Poller_Name='svcState' AND Status ='7' THEN 'OK'
WHEN Poller_Name='svcstate' AND Status ='4' THEN 'OUT OF SERVICE' END)
THEN CAST(Status AS bigint) ELSE '' END) svcState
FROM
(
SELECT
Nodes.Caption AS NodeName, CustomNodePollers_CustomPollers.UniqueName AS Poller_Name, CustomNodePollerStatus_CustomPollerStatus.Status AS Status, CustomNodePollerStatus_CustomPollerStatus.rowid as row, CustomNodePollerStatus_CustomPollerStatus.RawStatus as RawStatus
FROM
((Nodes INNER JOIN CustomPollerAssignment CustomNodePollerAssignment_CustomPollerAssignment ON (Nodes.NodeID = CustomNodePollerAssignment_CustomPollerAssignment.NodeID)) INNER JOIN CustomPollers CustomNodePollers_CustomPollers ON (CustomNodePollerAssignment_CustomPollerAssignment.CustomPollerID = CustomNodePollers_CustomPollers.CustomPollerID)) INNER JOIN CustomPollerStatus CustomNodePollerStatus_CustomPollerStatus ON (CustomNodePollerAssignment_CustomPollerAssignment.CustomPollerAssignmentID = CustomNodePollerStatus_CustomPollerStatus.CustomPollerAssignmentID)
WHERE
(
(CustomNodePollers_CustomPollers.UniqueName = 'svcServiceName') OR
(CustomNodePollers_CustomPollers.UniqueName = 'svcState')
)
AND
(
(CustomNodePollerAssignment_CustomPollerAssignment.InterfaceID = 0)
)
and Nodes.Caption = '101'
)A
GROUP BY NodeName, row
--ORDER BY svcServiceName
) B
Desired Output
MAX(CASE WHEN Poller_Name = 'svcState' THEN (CASE WHEN status = '7' THEN 'OK' ELSE 'DOWN' END) END)
Or...
MAX(CASE WHEN Poller_Name = 'svcState' AND status = '7' THEN 'OK'
WHEN Poller_Name = 'svcState' AND status = '4' THEN 'DOWN' END)
Or...
MAX(CASE WHEN Poller_Name != 'svcState' THEN NULL -- Assumes the poller_name is never NULL
WHEN status = '7' THEN 'OK'
WHEN status = '4' THEN 'DOWN'
END)
Where there is no ELSE specified, it is implicitly ELSE NULL, and NULL values are skipped by the MAX().

Sybase - Return only data from last three days

I am fairly new to this. I have a statement where I want to only return the last three days of data based on shipment_datedelivered. What date functions can I use to achieve this? I am using Sybase.
select dba.disp_ship.ds_id, dba.disp_ship.ds_origin_id, dba.disp_ship.ds_findest_id, dba.disp_ship.ds_billto_id, dba.disp_ship.ds_bill_charge, dba.disp_ship.ds_ref1_text,
dba.disp_ship.ds_status, dba.disp_ship.ds_bill_date, dba.disp_ship.ds_ship_date, dba.disp_ship.ds_ship_type, dba.disp_ship.movecode,
dba.companies.co_id, dba.companies.co_name, dba.current_shipments.cs_id, dba.current_shipments.cs_event_count, dba.current_shipments.cs_routed, dba.current_shipments.cs_assigned, dba.current_shipments.cs_completed, dba.current_shipments.shipment_datedelivered,
(CASE ds_status WHEN 'A' THEN 'TEMPLATE'
WHEN 'C' THEN 'CANCELLED'
WHEN 'D' THEN 'DECLINED'
WHEN 'E' THEN 'QUOTED'
WHEN 'F' THEN 'OFFERED'
WHEN 'H' THEN 'PENDING'
WHEN 'K' THEN 'OPEN'
WHEN 'N' THEN 'AUTHORIZED'
WHEN 'Q' THEN 'AUDIT REQUIRED'
WHEN 'T' THEN 'AUDITED'
WHEN 'W' THEN 'BILLED'
END) AS 'BILLING STATUS',
(CASE ds_ship_type WHEN '2201' THEN 'MONTREAL'
WHEN '2202' THEN 'DRYVAN'
WHEN '2203' THEN 'BROKERAGE'
WHEN '2204' THEN 'OLD BROKERAGE (NO GOOD)'
WHEN '2205' THEN 'LIFTING'
WHEN '2206' THEN 'WAREHOUSE'
END) AS 'DIVISION',
(CASE WHEN dba.current_shipments.cs_event_count = dba.current_shipments.cs_completed
THEN 'OPEN COMPLETED'
ELSE 'INCOMPLETE'
END)
AS 'STATUS'
from dba.disp_ship
inner join dba.companies ON dba.disp_ship.ds_billto_id=dba.companies.co_id
inner join dba.current_shipments ON dba.disp_ship.ds_id=DBA.current_shipments.cs_id
Well, I think I just got it. I added this to the end of my query and I am now getting the desired data.
where shipment_datedelivered >= dateadd(day, -3, GETDATE())

Select is not valid at this position for this server version, expecting: '(', WITH

I get a syntax error with my SQL statement and I don't know where it is wrong. I'll greatly appreciate it if anyone here can shed some light. Thanks in advance!
SELECT YEAR(co.CO_APPLIED_DT) as SCO_YEAR
,MONTH(co.CO_APPLIED_DT) as SCO_MONTH_ID
,co.CO_OWNER_ACCNID as SCO_APPL_ACCNID
,co.CO_APPROVER_ACCNID as SCO_APPR_ACCNID
,co.CO_ISSUE_CTRY_CD as SCO_ISSUE_CTRY_CD
,co.CO_FINALDEST_CTRY_CD as SCO_DEST_CTRY_CD
,'99999999' AS SCO_HS_CHAP_CD
,SUM(CASE
WHEN co.CO_STATUS IN ('A','P', 'T', 'E', 'C', 'F', 'L') THEN 1
ELSE 0
END) AS SCO_APPROVED_CT
,SUM(CASE
WHEN co.CO_STATUS = 'U' THEN 1
ELSE 0
END) AS SCO_CANCELLED_CT
,SUM(CASE
WHEN co.CO_STATUS = 'R' THEN 1
ELSE 0
END) AS SCO_REJECTED_CT
,0 AS SCO_HS_CHAP_CT
FROM TDocCo co
WHERE co.CO_STATUS NOT IN ('N', 'D')
AND co.CO_APPLIED_DT <= :date
AND YEAR(co.CO_APPLIED_DT) = :year
AND MONTH(co.CO_APPLID_DT) = :month
GROUP BY co.CO_APPROVER_ACCNID
,co.CO_OWNER_ACCNID
,co.CO_ISSUE_CTRY_CD
,co.CO_FINALDEST_CTRY_CD
,YEAR(co.CO_APPLIED_DT)
,MONTH(co.CO_APPLIED_DT);
I'm getting the error message as shown above.
These are my 2 cents:
In my local Db I wrote your query, only changing parameters :date :year and :month with today values. It seems right!
SELECT
getDate() as CO_APPLIED_DT,
23 as CO_OWNER_ACCNID,
42 as CO_APPROVER_ACCNID,
'England' as CO_ISSUE_CTRY_CD,
'Poland' as CO_FINALDEST_CTRY_CD,
'A' as CO_STATUS
INTO TDocCo
SELECT YEAR(co.CO_APPLIED_DT) as SCO_YEAR,
MONTH(co.CO_APPLIED_DT) as SCO_MONTH_ID,
co.CO_OWNER_ACCNID as SCO_APPL_ACCNID,
co.CO_APPROVER_ACCNID as SCO_APPR_ACCNID,
co.CO_ISSUE_CTRY_CD as SCO_ISSUE_CTRY_CD,
co.CO_FINALDEST_CTRY_CD as SCO_DEST_CTRY_CD,
'99999999' AS SCO_HS_CHAP_CD,
SUM(CASE WHEN co.CO_STATUS IN ('A','P', 'T', 'E', 'C', 'F', 'L') THEN 1 ELSE 0 END) AS SCO_APPROVED_CT,
SUM(CASE WHEN co.CO_STATUS = 'U' THEN 1 ELSE 0 END) AS SCO_CANCELLED_CT,
SUM(CASE WHEN co.CO_STATUS = 'R' THEN 1 ELSE 0 END) AS SCO_REJECTED_CT,
0 AS SCO_HS_CHAP_CT
FROM TDocCo co
WHERE co.CO_STATUS NOT IN ('N', 'D')
AND co.CO_APPLIED_DT <= getDate() -- modified
AND YEAR(co.CO_APPLIED_DT) = year (getDate()) -- modified
AND MONTH(co.CO_APPLIED_DT) = month (getDate()) -- modified
GROUP BY co.CO_APPROVER_ACCNID, co.CO_OWNER_ACCNID, co.CO_ISSUE_CTRY_CD, co.CO_FINALDEST_CTRY_CD, YEAR(co.CO_APPLIED_DT), MONTH(co.CO_APPLIED_DT);
DROP TABLE TDocCo

One date check for entire query

I have the following query:
select
fp.id,
fr.id,
sum(case
when to_date(fp.offered_date) BETWEEN TO_DATE( :ad_startdate, 'YYYY-MM-DD')
AND TO_DATE(:ad_enddate, 'YYYY-MM-DD') and fp.result <> 'E'
then 1
else 0
end) total,
sum(case when fp.result = 'G'
and to_date(fp.offered_date) >= :ad_startdate
and to_date(fp.offered_date) <= :ad_enddate then 1 else 0 end) colorgreen,
sum(case when fp.resultat = 'R'
and to_date(fp.offered_date) >= :ad_startdate
and to_date(fp.offered_date) <= :ad_enddate then 1 else 0 end) colorred
FROM
fruit_properties fp, fruit fr
WHERE
fp.id = fr.id
GROUP BY
fp.id, fr.id
I'm checking dates 1 time for each sum column and have a feeling this can be made once somehow? Right now if I check only once at the total column, then colorgreen + colorred might be larger than the total since it counts no matter what date they have.
Can my query be enhanced somehow?
you can simplify like this. but PLEASE check your SQL. you're mixing TO_DATE and CHAR datatypes. this will only end in disaster.
eg you have:
when to_date(fp.offered_date) BETWEEN TO_DATE( :ad_startdate, 'YYYY-MM-DD')
AND TO_DATE(:ad_enddate, 'YYYY-MM-DD')
vs
sum(case when fp.result = 'G'
and to_date(fp.offered_date) >= :ad_startdate
in one case you are TO_DATE'ing ad_startdate but not another (so is it a date already or not?). you are also TO_DATEing the column but crucially WITHOUT a format mask. is the column really a VARCHAR datatype? if so you really should not store dates as anything but DATEs.
anyway assuming the column is a DATE datatype and the binds are of type DATE..
select fruit_prop_Id,fruit_id,
sum(case when result != 'E' then within_offer else 0 end) total,
sum(case when result = 'R' then within_offer else 0 end) colorred,
sum(case when result = 'G' then within_offer else 0 end) colorgreen
from (select fp.id fruit_id,
fr.id fruit_prop_Id,
fp.result,
case
when fp.offered_date >= :ad_startdate
and fp.offered_date <= :ad_enddate then 1 else 0 end within_offer
from fruit_properties fp, fruit fr
where fp.id = fr.id)
group by fruit_id, fruit_prop_Id
You can put the date check in the where clause:
select
fp.id,
fr.id,
sum(case when and fp.result <> 'E' then 1 else 0 end) total,
sum(case when fp.result = 'G' then 1 else 0 end) colorgreen,
sum(case when fp.resultat = 'R' then 1 else 0 end) colorred
FROM
fruit_properties fp, fruit fr
WHERE
fp.id = fr.id
AND to_date(fp.offered_date) >= :ad_startdate
AND to_date(fp.offered_date) <= :ad_enddate
GROUP BY
fp.id, fr.id
Edit: as pointed out in the comments, this query will filter out ids which doesn't have any offer dates in the given interval.

Odd GROUP BY output DB2 - Results not as expected

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