Multiple when condition in case statement - teradata

I have wrote below code , it is working as expected but its taking too much of time.
`SELECT COUNT(SRC.DVC_ID),'AUDIO' AS FEATURE,'PDPN ' AS COL_NAME, 'DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY ' AS SRC_TABLE,'DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT' AS TGT_TABLE
FROM DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY SRC
JOIN DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT TGT
ON SRC.DVC_ID=TGT.DVC_ID AND SRC.PDPN<>TGT.PDPN
WHERE TGT.CUR_REC_FL='Y' AND SRC.AUDO_STS IN('A','S') AND SRC.AUDO_PROD_ID IS NOT NULL AND UPPER(SRC.DELV_METH)<>'TELEMATICS'
UNION ALL
SELECT COUNT(SRC.DVC_ID),'AUDIO' AS FEATURE,'PSN' AS COL_NAME, 'DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY ' AS SRC_TABLE,'DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT' AS TGT_TABLE
FROM DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY SRC
JOIN DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT TGT
ON SRC.DVC_ID=TGT.DVC_ID AND SRC.PSN<>TGT.PSN
WHERE TGT.CUR_REC_FL='Y' AND SRC.AUDO_STS IN('A','S') AND SRC.AUDO_PROD_ID IS NOT NULL AND UPPER(SRC.DELV_METH)<>'TELEMATICS'
UNION ALL
SELECT COUNT(SRC.DVC_ID),'AUDIO' AS FEATURE,'PTNR_ID' AS COL_NAME, 'DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY ' AS SRC_TABLE,'DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT' AS TGT_TABLE
FROM DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY SRC
JOIN DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT TGT
ON SRC.DVC_ID=TGT.DVC_ID AND SRC.PTNR_ID<>TGT.PTNR_ID
WHERE TGT.CUR_REC_FL='Y' AND SRC.AUDO_STS IN('A','S') AND SRC.AUDO_PROD_ID IS NOT NULL AND UPPER(SRC.DELV_METH)<>'TELEMATICS'
UNION ALL
SELECT COUNT(SRC.DVC_ID),'AUDIO' AS FEATURE,'PTNR_NM' AS COL_NAME, 'DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY ' AS SRC_TABLE,'DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT' AS TGT_TABLE
FROM DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY SRC
JOIN DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT TGT
ON SRC.DVC_ID=TGT.DVC_ID AND SRC.PTNR_NM<>TGT.PTNR_NM
WHERE TGT.CUR_REC_FL='Y' AND SRC.AUDO_STS IN('A','S') AND SRC.AUDO_PROD_ID IS NOT NULL AND UPPER(SRC.DELV_METH)<>'TELEMATICS'
UNION ALL
SELECT COUNT(SRC.DVC_ID),'AUDIO' AS FEATURE,'SEC_PTNR_ID' AS COL_NAME, 'DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY ' AS SRC_TABLE,'DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT' AS TGT_TABLE
FROM DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY SRC
JOIN DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT TGT
ON SRC.DVC_ID=TGT.DVC_ID AND SRC.SEC_PTNR_ID<>TGT.SEC_PTNR_ID
WHERE TGT.CUR_REC_FL='Y' AND SRC.AUDO_STS IN('A','S') AND SRC.AUDO_PROD_ID IS NOT NULL AND UPPER(SRC.DELV_METH)<>'TELEMATICS' `
So i have modifed the query as below, But the output is wrong.
SELECT * FROM(
SELECT COUNT(SRC.DVC_ID)OVER(PARTITION BY COL_NAME ) AS DVC_ID_CNT,
'TRFC' AS FEATURE,
CASE WHEN SRC.PDPN<>TGT.PDPN THEN 'PDPN '
WHEN SRC.PSN<>TGT.PSN THEN 'PSN '
WHEN SRC.PTNR_ID<>TGT.PTNR_ID THEN 'PTNR_ID'
WHEN SRC.SEC_PTNR_ID<>TGT.SEC_PTNR_ID THEN 'SEC_PTNR_ID'
WHEN SRC.SEC_PTNR_ID<>TGT.SEC_PTNR_ID THEN 'SEC_PTNR_ID' ELSE '0' END COL_NAME
,'DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY' AS SRC_TABLE,'DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT' AS TGT_TABLE
FROM DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY SRC
JOIN DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT TGT ON SRC.DVC_ID=TGT.DVC_ID
WHERE TGT.CUR_REC_FL='Y' AND SRC.AUDO_STS IN('A','S') AND SRC.AUDO_PROD_ID IS NOT NULL AND UPPER(SRC.DELV_METH)<>'TELEMATICS'
AND COL_NAME<>'0'
)A GROUP BY 1,2,3,4,5
Please suggest.
Thanks in advance

This query is too complicated, no need for COUNT OVER plus GROUP BY, a simple COUNT is enough.
Assuming that a single row can satisfy multiple WHENs the result will be wrong anyway, because a CASE can't be used to return multiple values/rows, it's always the first match.
The only way to get this in a single pass over the table is pivoting:
SELECT
Count(CASE WHEN SRC.PDPN<>TGT.PDPN THEN 1 END) AS PDPN,
Count(CASE WHEN SRC.PSN<>TGT.PSN THEN 1 END) AS PSN,
Count(CASE WHEN SRC.PTNR_ID<>TGT.PTNR_ID THEN 1 END) AS PTNR_ID,
Count(CASE WHEN SRC.SEC_PTNR_ID<>TGT.SEC_PTNR_ID THEN 1 END) AS SEC_PTNR_ID,
'TRFC' AS FEATURE,
,'DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY' AS SRC_TABLE
,'DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT' AS TGT_TABLE
FROM DP_VEDW_TRM.V_DEVICE_VIEW_SUMMARY SRC
JOIN DP_VEDW_SRC_MDB_NGN.DVC_SUM_AUDO_VIEW_HIST_PT TGT
ON SRC.DVC_ID=TGT.DVC_ID
WHERE TGT.CUR_REC_FL='Y'
AND SRC.AUDO_STS IN('A','S')
AND SRC.AUDO_PROD_ID IS NOT NULL
AND Upper(SRC.DELV_METH)<>'TELEMATICS'
Of course you could unpivot this again using WITH to match the 1st result :-)
WITH cte AS
(
previous query plus DISTINCT
!!!must add DISTINCT to force the optimizer to materialize the result!!!
)
SELECT PDPN, 'PDPN', FEATURE, SRC_TABLE, TGT_TABLE FROM cte
UNION ALL
SELECT PSN, 'PSN', FEATURE, SRC_TABLE, TGT_TABLE FROM cte
UNION ALL
...

Related

Crafting a Subquery-able UNION ALL based on the results of a query

Data
I have a couple of tables like so:
CREATE TABLE cycles (
`cycle` varchar(6) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`cycle_type` varchar(140) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`start` date DEFAULT NULL,
`end` date DEFAULT NULL
);
CREATE TABLE rsvn (
`str` varchar(140) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`start_date` date DEFAULT NULL,
`end_date` date DEFAULT NULL
);
INSERT INTO `cycles` (`cycle`, `cycle_type`, `start`, `end`) values
('202013', 'a', '2021-01-04', '2021-01-31'),
('202013', 'b', '2021-01-04', '2021-01-31'),
('202101', 'a', '2021-01-04', '2021-01-31'),
('202101', 'b', '2021-01-04', '2021-01-31'),
('202102', 'a', '2021-02-01', '2021-02-28'),
('202102', 'b', '2021-02-01', '2021-02-28'),
('202103', 'a', '2021-03-01', '2021-03-28'),
('202103', 'b', '2021-03-01', '2021-03-28');
INSERT INTO `rsvn` (str, start_date, end_date) values
('STR01367', '2020-12-07', '2020-06-21'),
('STR00759', '2020-12-07', '2021-04-25'),
('STR01367', '2021-01-04', '2021-09-12'),
('STR01367', '2021-06-21', '2022-02-27');
Desired Results
For any given cycle, I want to count the number of occurrences of str across cycles. So between cycle 2108 - 2108 (one cycle), I see:
str
count
STR01367
1
STR00759
1
And from between 2108 - 2109 (two cycles) I see:
str
count
STR01367
2
STR00759
1
What I've tried
I'm trying to figure out how to dynamically obtain those results. I don't see any options outside a UNION ALL query (one query for each cycles), so I tried writing a PROCEDURE. However, that didn't work because I want to do post-processing on the query results, and I don't believe you can use the results of a PROCEDURE in a CTE or subquery.
My PROCEDURE (works, can't include results in a subquery like SELECT * FROM call count_cycles (?)):
CREATE PROCEDURE `count_cycles`(start_cycle CHAR(6), end_cycle CHAR(6))
BEGIN
SET #cycles := (
SELECT CONCAT('WITH installed_cycles_count AS (',
GROUP_CONCAT(
CONCAT('
SELECT rsvn.str, 1 AS installed_cycles
FROM rsvn
WHERE "', `cy`.`start`, '" BETWEEN rsvn.start_date AND COALESCE(rsvn.end_date, "9999-01-01")
OR "', `cy`.`end`, '" BETWEEN rsvn.start_date AND COALESCE(rsvn.end_date, "9999-01-01")
GROUP BY rsvn.str
'
)
SEPARATOR ' UNION ALL '
),
')
SELECT
store.chain AS "Chain"
,store.division AS "Division"
,dividers_store AS "Store"
,SUM(installed_cycles) AS "Installed Cycles"
FROM installed_cycles_count r
LEFT JOIN store ON store.name = r.dividers_store
GROUP BY dividers_store
ORDER BY chain, division, dividers_store, installed_cycles'
)
FROM cycles `cy`
WHERE `cy`.`cycle_type` = 'Ad Cycle'
AND `cy`.`cycle` >= CONCAT('20', RIGHT(start_cycle, 4))
AND `cy`.`cycle` <= CONCAT('20', RIGHT(end_cycle, 4))
GROUP BY `cy`.`cycle_type`
);
EXECUTE IMMEDIATE #cycles;
END
Alternatively, I attempted to use a recursive query to obtain my results by incrementing my cycle. This gave me the cycles I wanted:
WITH RECURSIVE xyz AS (
SELECT cy.`cycle`, cy.`start`, cy.`end`
FROM cycles cy
WHERE cycle_type = 'Ad Cycle'
AND `cycle` = '202101'
UNION ALL
SELECT cy.`cycle`, cy.`start`, cy.`end`
FROM xyz
JOIN cycles cy
ON cy.`cycle` = increment_cycle(xyz.`cycle`, 1)
AND cy.`cycle_type` = 'Ad Cycle'
WHERE cy.`cycle` <= '202110'
)
SELECT * FROM xyz;
But I can't get it working when I add in the reservations table:
infinite loop?
WITH RECURSIVE xyz AS (
SELECT cy.`cycle`, 'dr.dividers_store', 1 AS installed_cycles
FROM cycles cy
LEFT JOIN rsvn dr
ON cy.`start` BETWEEN dr.start_date AND COALESCE(dr.end_date, "9999-01-01")
OR cy.`end` BETWEEN dr.start_date AND COALESCE(dr.end_date, "9999-01-01")
WHERE cy.`cycle_type` = 'Ad Cycle'
AND cy.`cycle` = '202101'
UNION ALL
SELECT cy.`cycle`, 'dr.dividers_store', 1 AS installed_cycles
FROM xyz
JOIN cycles cy
ON cy.`cycle` = increment_cycle(xyz.`cycle`, 1)
AND cy.`cycle_type` = 'Ad Cycle'
LEFT JOIN rsvn dr
ON cy.`start` BETWEEN dr.start_date AND COALESCE(dr.end_date, "9999-01-01")
OR cy.`end` BETWEEN dr.start_date AND COALESCE(dr.end_date, "9999-01-01")
WHERE cy.`cycle` <= '202102'
)
SELECT * FROM xyz
What options do I have to get the results I need, in such a way that I can use them in a CTE or subquery?
The results I am looking for are easily obtained via a two-stage grouping. Something like this:
WITH sbc AS (
SELECT cy.`cycle`, dr.str, 1 AS 'count'
FROM cycles cy
LEFT JOIN rsvn dr
ON cy.`start` BETWEEN dr.start_date AND dr.end_date
OR cy.`end` BETWEEN dr.start_date AND dr.end_date
WHERE cy.`cycle_type` = 'Ad Cycle'
AND cy.`cycle` BETWEEN '202201' AND '202205'
GROUP BY cy.`cycle`, dr.str
ORDER BY dr.str, cy.`cycle`
)
SELECT `cycle`, str, SUM(`count`) as `count`
FROM sbc
GROUP BY str
The CTE produces one result per rsvn per cycle. Afterwards all that is needed is to group by store and count the number of occurrences.
Besides being simpler, I suspect that this query is faster than the union concept I was stuck on when I asked the question, since among other things the server does not need to perform a union on multiple grouping queries. However, I do not understand how MariaDB optimizes such queries, and while I am curious I don't have the time to run benchmarks to find out.

Is there any way to accomplish this in IBM DB2 enviroment

In DB2 is there a way to basically say:
case when sku (select * from table1 where tb1field = 'SMOMD') then 'True' end
Okay so this is my query so far, I've been going at this for at least a month now so any help would be great.
select tb4.customer, tb4.sku, tb4.qty, tb4.retqty, tb4.stipqty, tb4.lastdate, tb4.firstdate, tb4.stipdate
from(
--Table 4
select tb3.Customer as Customer, tb3.sku as SKU, tb3.qty as Qty, tb3.retqty as RetQty, tb3.stipqty as STIPQty,
case when tb3.lastdate is null then '00/0000' else substr(tb3.lastdate,5,2)||'/'||substr(tb3.lastdate,1,4) end as LastDate,
case when tb3.firstdate is null then '00/0000' else substr(tb3.firstdate,5,2)||'/'||substr(tb3.firstdate,1,4) end as FirstDate,
case when tb3.stipdate is null then '00/0000' else substr(tb3.stipdate,5,2)||'/'||substr(tb3.stipdate,1,4) end as STIPDate
from(
--Table 3
select tb2.Customer as Customer, tb2.SKU as SKU, tb2.Qty as Qty, tb2.RetQty as RetQty, tb2.STIPQty as STIPQty,
max(case when tb2.TranID in ('010','100') then tb2.datenum end) as LastDate,
min(case when tb2.TranID in ('010','100') then tb2.datenum end) as FirstDate,
case when tb2.RC = '4M' then tb2.datenum end as STIPDate
from(
--Table 2
select tb1.Customer as Customer, tb1.SKU as SKU,
sum(case when tb1.TranID in ('010','100') then abs(tb1.OrdNet) else '0' end) as Qty,
sum(case when tb1.TranID = '500' and tb1.rc != '4M' then abs(tb1.OrdNet) else '0' end) as RetQty,
count(case when tb1.rc = '4M' then tb1.sku end) as STIPQty,
tb1.datenum as datenum, tb1.TranID as tranid, tb1.RC as rc
from(
--Table 1
select distinct stkund as Customer, sthptg||space(1)||stmodl||space(1)||stvari||space(1)||stfarb||space(1)||stgroe as SKU,
stvorg as TranID, stggru as RC, stprg09 as PG9, stprg08 as PG8, stperi as datenum, ormne1 as OrdNet
from st_usus.s_stati_pv
join caspdtau.cospf440 on stadrn = jadr40
where trim(stvert) in ('111S','122S')
and sthptg != 'V'
and aktv40 = 'A'
and stprg01 in ('01','04')
and stprg02 = '01'
and stvorg in ('500','010','100')
and stperi >= '20160100'
) as tb1
group by tb1.Customer, tb1.SKU, tb1.datenum, tb1.tranid, tb1.rc
) as tb2
group by tb2.customer, tb2.sku, tb2.qty, tb2.retqty, tb2.stipqty, tb2.tranid, tb2.rc, tb2.datenum
) as tb3
group by tb3.customer, tb3.sku, tb3.qty, tb3.retqty, tb3.stipqty, tb3.lastdate, tb3.firstdate, tb3.stipdate
) as tb4
order by tb4.Customer, tb4.sku
I'm not going to try to decipher exactly what you're trying to do...
Some general advice, rather than using Nested Table Expressions (NTE)
select <..> from (select <...>from mytable)
Consider Common Table Expressions (CTE)
with
table1 as (select <...> from st_usus.s_stati_pv join caspdtau.cospf440 on stadrn = jadr40)
, table2 as (select <...> from table1)
, table3 as (select <...> from table2)
, table4 as (select <....> from table3)
select <...> from table4;
Each CTE (ie. tableX) can refer to a prior CTE or a physical table/view as needed. The final select can refer to one or more CTE's along with one or more physical tables or views.
Nice thing about building with CTE's, is that you can check your results after each step..
with
table1 as (select <...> from st_usus.s_stati_pv join caspdtau.cospf440 on stadrn = jadr40)
select * from table1;

How to select gaps in my sqlite database

I'm trying to write down a select to show me all the items that do not exist in my database. Say I have a table named TBL795 with a column named NRBEM which could not have any gaps in it.
Should be this way:
Those numbers are in sequence.
If they looked like this:
they would be wrong, because some items have not being inserted into the table.
In a table with thousand of items it would be very difficult to find out if there are any gaps and which are the missing items.
One solution would be this:
CREATE TABLE TESTE (
NRBEM VARCHAR(15))
feed it with a command like this:
INSERT INTO TESTE
WITH RECURSIVE
cnt(NRBEM) AS (VALUES(1) UNION ALL SELECT NRBEM+1 FROM cnt WHERE NRBEM <100000)
SELECT NRBEM FROM cnt A
and running this select
SELECT A.NRBEM FROM TESTE A LEFT JOIN TBL795 B
ON A.NRBEM = B.NRBEM
WHERE B.NRBEM IS NULL
I can see all the items that are missing in my table.
Since the command:
WITH RECURSIVE
cnt(NRBEM) AS (VALUES(1) UNION ALL SELECT NRBEM+1 FROM cnt WHERE NRBEM <100000)
SELECT NRBEM FROM cnt
create a virtual table I would like to run a select like this:
SELECT NRBEM FROM (
WITH RECURSIVE
cnt(NRBEM) AS (VALUES(1) UNION ALL SELECT NRBEM+1 FROM cnt WHERE NRBEM <100000)
SELECT NRBEM FROM cnt ) A LEFT JOIN TBL795 B
ON A.NRBEM = B.NRBEM
But this does not work.
This way:
SELECT X FROM (
WITH RECURSIVE
cnt(X) AS (VALUES(1) UNION ALL SELECT X+1 FROM cnt WHERE X <100000)
SELECT X FROM cnt ) A LEFT JOIN TBL795 B
ON A.X = B.NRBEM
it works, but does not select the right items.
So, how could I write this select?
It would be possible to use an outer join and filter out matches, but using set operations is simpler:
WITH RECURSIVE CNT(NRBEM) AS (...)
SELECT NRBEM
FROM CNT
WHERE NRBEM NOT IN (SELECT NRBEM
FROM tbl795);
I found out what I was doing wrong.
If I cast nrbem as number the select works.
SELECT A.X FROM (
WITH RECURSIVE
cnt(X) AS (VALUES(1) UNION ALL SELECT X+1 FROM cnt WHERE X <100000)
SELECT X FROM cnt ) A LEFT JOIN ( SELECT CAST( NRBEM AS NUMBER ) AS NRBEM FROM TBL795 ) B
ON A.X = B.NRBEM
WHERE B.NRBEM IS NULL
If I want to check the range from item 2400 to 2700 to see if there are any gaps I can do this:
SELECT A.X FROM (
WITH RECURSIVE
cnt(X) AS (VALUES(2400) UNION ALL SELECT X+1 FROM cnt WHERE X < (2700))
SELECT X FROM cnt ) A LEFT JOIN ( SELECT CAST( NRBEM AS NUMBER ) AS NRBEM FROM TBL795 WHERE NRBEM >= 2400 and nrbem <= 2700 ) B
ON A.X = B.NRBEM
WHERE B.NRBEM IS NULL
LIMIT ( 2700 - 2400 + 1 )

Query run result in Teradata

I am running below query in Teradata editor:
SELECT 'EMP_INFO_MAIN' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE1 UNION ALL
SELECT 'EMP_SAL' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE2 UNION ALL
SELECT 'DEPARTMENT_INFO' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE3;
The query is giving me below result:
TABLE_NAME | RECORD_COUNT
------------|-------------
EMP_INFO | 10
EMP_SAL | 11
DEPARTME | 110
The first column is not showing complete table name.
Can anyone please help here?
This is a common issue.
In Teradata the first SELECT of a UNION determines the resulting data typ and the column name, so either change the order of SELECTs to start with the longest name or add a CAST in the 1st SELECT:
SELECT CAST('EMP_INFO_MAIN' AS VARCHAR(20)) as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE1 UNION ALL
SELECT 'EMP_SAL' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE2 UNION ALL
SELECT 'DEPARTMENT_INFO' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE3;

SQLite: Trying to concatenate columns in more elegant way than string of UNIONs

I have a table with the following fields and example value:
coursecode BIO 101
a_code FA
b_code SP
c_code SU
d_code
e_code
I'm trying to populate a field in another table (using coursecode as the key) with a comma separated list of all the "code" fields that have values (i.e. "FA, SP, SU"). I am accomplishing this successfully with the following code, but it is messy and was wondering if there was a more elegant way to accomplish this (esp. without all the UNION statements):
SELECT coursecode, group_concat(codes)
FROM (
SELECT
coursecode,
a_code AS codes
FROM scbsupp
WHERE coursecode="BIO 317"
UNION
SELECT coursecode,
b_code AS codes
FROM scbsupp
WHERE coursecode="BIO 317"
UNION
SELECT
coursecode,
c_code AS codes
FROM scbsupp
WHERE coursecode="BIO 317"
UNION
SELECT coursecode,
d_code AS codes
FROM scbsupp
WHERE coursecode="BIO 317"
UNION
SELECT coursecode,
e_code AS codes
FROM scbsupp
WHERE coursecode="BIO 317"
) WHERE codes != "";
For my own knowledge I would like to know if there's a better way to do this, I appreciate any help!
You can do:
SELECT coursecode,
LTRIM(
CASE WHEN (a_code IS NOT NULL AND a_code <> '') THEN a_code ELSE '' END ||
CASE WHEN (b_code is NOT NULL AND b_code <> '') THEN ',' || b_code ELSE '' END ||
CASE WHEN (c_code IS NOT NULL AND c_code <> '') THEN ',' || c_code ELSE '' END ||
CASE WHEN (d_code IS NOT NULL AND d_code <> '') THEN ',' || d_code ELSE '' END ||
CASE WHEN (e_code IS NOT NULL AND e_code <> '') THEN ',' || e_code ELSE '' END, ','
) AS code
FROM scbsupp
WHERE coursecode="BIO 317"
;

Resources