Combine rows on case when with non numeric - sql

HI all i'm trying to get all rows rolled up to one. I have tried MAX Case when but there is a non numeric string in the case when and it isn't working to roll up the data. I have tried to find other examples but can't so i'm asking for your help. Thanks in advance
I have two fields that have different data but all have the same control number and i need to get all data for the control number rolled into one row.
SELECT CNTL_NUM
,TRANS_TYP
,CASE WHEN SEQ_NUM = '02' THEN SUBSTRING(TRANS_INFO,28,9) END AS 'SSN'
,CASE WHEN SEQ_NUM = '11' THEN SUBSTRING(TRANS_INFO,46,2) END AS 'IPS_STATE'
FROM LVJPROD.IPS_LNA
WHERE TRANS_TYP = 'TA'
GROUP BY CNTL_NUM, TRANS_TYP,SEQ_NUM,TRANS_INFO
order by CNTL_NUM
I am hoping to get all 6 lines rolled up to one from the screen shot below

You can group them again. The problem is with the case statement where it manipulates data. So you need to treat these as a subquery and have a grouping in the outer query and the MAX should work
WITH yourtable
AS (SELECT cntl_num,
trans_typ,
CASE
WHEN seq_num = '02' THEN Substring(trans_info, 28, 9)
END AS ssn,
CASE
WHEN seq_num = '11' THEN Substring(trans_info, 46, 2)
END AS ips_state
FROM lvjprod.ips_lna
WHERE trans_typ = 'TA'
GROUP BY cntl_num,
trans_typ,
seq_num,
trans_info)
SELECT cntl_num,
trans_typ,
Max(ssn),
Max(ips_state)
FROM yourtable
GROUP BY cntl_num,
trans_typ
ORDER BY cntl_num;
OR
SELECT cntl_num,
trans_typ,
Max(ssn),
Max(ips_state)
FROM (SELECT cntl_num,
trans_typ,
CASE
WHEN seq_num = '02' THEN Substring(trans_info, 28, 9)
END AS ssn,
CASE
WHEN seq_num = '11' THEN Substring(trans_info, 46, 2)
END AS ips_state
FROM lvjprod.ips_lna
WHERE trans_typ = 'TA'
GROUP BY cntl_num,
trans_typ,
seq_num,
trans_info) a
GROUP BY cntl_num,
trans_typ
ORDER BY cntl_num;

Related

How to present a particular SQL queried row as columns in output

I need to present the attached output in PIC1 as the result in PIC2. The query used for generating PIC1 output in SQLDeveloper:
select subs_nm, as_of_date, run_status, (select max (tp.pr_vl)
from ual_mng.tqueue tq, ual_mng.tparams tp, ual_mng.tstatus ts
WHERE tq.tid = tp.tid AND tq.tid = ts.tid and tq.run_id = pcm.run_id and tp.pr_nm in ('TOT_RECORD_CNT')) as RECORD_COUNT
from UAL_MNG.PCM_SUBS_RUN_DTL_VW pcm where SUBS_NM='S_TS2_AQUA_A1_RLAP_DL' and AS_OF_DATE in ('2021-09-01','2021-09-02') order by run_start_dtm desc;
Appreciate all help.
If you don't need it to be dynamic (ie. it will only be two columns and you know which two months they are) you can do
select subs_nm,
max(case when as_of_date = '2021-09-01' then RECORD_COUNT else 0 end) as SEP1,
max(case when as_of_date = '2021-09-02' then RECORD_COUNT else 0 end) as SEP2,
from (
-- Your query
)
group by subs_nm
You can work out the percentage difference using the same expressions.
nb. I would always use an explicit date format mask. This might not run on a different machine / software. So use to_date('2021-09-01', 'yyyy-mm-dd')
Posting the query, which worked in the script :
select subs_nm, SEP1, SEP2, round((((SEP1-SEP2)/SEP1)*100),2) as DIFF_PER from ( select subs_nm,
max(case when as_of_date='2021-09-01' then RECORD_COUNT else '0' end) as SEP1,
max(case when as_of_date='2021-09-02' then RECORD_COUNT else '0' end) as SEP2 from (-- *Main Query*);

SQL: create if condition for grouped variables

I have a table with 4 columns and need to create a newcolumn, which represents that if for the following year's quarter exists at least one data='colour', so for this quarter all values are changed to 'colour. How to do it?
You can use condition and get count of no for each quarter as follows:
select t.*,
case when count(case when data = 'no' then 1 end)
over (partition by year, quarter) > 0
then 'nocolour'
else data
end as new_column
from your_table t
You can use window functions:
select t.*,
min(data) over(partition by year, quarter) as new_column
from mytable t
If there is any 'no' for a given quarter, new_column takes value 'no' for all rows of the quarter. This works because string-wise, 'no' < 'yes'.
Assuming that you really mean "has data = 'yes' and the next quarter and you want to update the table, you can use:
update t
set newcolumn = (case when next_max_data = 'yes' then 'colour' else 'no colour')
from t join
(select year, quarter,
lead(max(data)) over (order by year, quarter) as next_max_data
from t
group by year, quarter
) tt
on t.year = tt.year and t.quater = tt.quarter;
If you want the the quarter a year later, you would use lead(max(data), 4) in the subquery.

Sql out put which come into multiple row converted to single row

This query give multiple row which needs to be shown in single row. Please help.
SELECT blng_serv_code, (COUNT (blng_serv_code)) AS total ,
DECODE (package_trx_yn, 'Y', 'PKG', 'N', 'NPKG') pkg_status FROM bl_patient_charges_folio
WHERE operating_facility_id = 'MC'
AND trx_date >= TO_DATE ('10/10/2019 00:00:00', 'MM/DD/YYYY HH24:MI:SS')AND blng_serv_code = 'LBSB000015'
GROUP BY blng_serv_code, package_trx_yn
If you want the value in a single row, leave out the package status:
SELECT blng_serv_code, COUNT(*) AS total
FROM bl_patient_charges_folio
WHERE operating_facility_id = 'MC' AND
trx_date >= DATE '2019-10-10' AND
blng_serv_code = 'LBSB000015'
GROUP BY blng_serv_code;
If you do want the package status, then you need to explain the logic for including it "on a single row".
EDIT:
It sounds like you want the values in separate columns:
SELECT blng_serv_code, COUNT(*) AS total,
SUM(CASE WHEN package_trx_yn = 'Y' THEN 1 ELSE 0 END) as pkg_cnt,
SUM(CASE WHEN package_trx_yn = 'N' THEN 1 ELSE 0 END) as npkg_cnt
FROM bl_patient_charges_folio
WHERE operating_facility_id = 'MC' AND
trx_date >= DATE '2019-10-10' AND
blng_serv_code = 'LBSB000015'
GROUP BY blng_serv_code;

MSSQL Group by and Select rows from grouping

I'm trying to figure out if what I'm trying to do is possible. Instead of resorting to multiple queries on a table, I wanted to group the records by business date and id then group by the id and select one date for a field and another date for the other field.
SELECT
*
{AMOUNT FROM DATE}
{AMOUNT FROM OTHER DATE}
FROM (
SELECT
date,
id,
SUM(amount) AS amount
FROM
table
GROUP BY id, date
AS subquery
GROUP BY id
It seems that you're looking to do a pivot query. I usually use cross tabs for this. Based on the query you posted, it could look like:
SELECT
id,
SUM(CASE WHEN date = '20190901' THEN amount ELSE 0 END) AmountFromSept01,
SUM(CASE WHEN date = '20191001' THEN amount ELSE 0 END) AmountFromOct01
FROM (
SELECT
date,
id,
SUM(amount) AS amount
FROM
table
GROUP BY id, date
)AS subquery
GROUP BY id;
You could also use a CTE.
WITH CTE AS(
SELECT
date,
id,
SUM(amount) AS amount
FROM
table
GROUP BY id, date
)
SELECT
id,
SUM(CASE WHEN date = '20190901' THEN amount ELSE 0 END) AmountFromSept01,
SUM(CASE WHEN date = '20191001' THEN amount ELSE 0 END) AmountFromOct01
FROM CTE
GROUP BY id;
Or even be a rebel and do the operation directly.
SELECT
id,
SUM(CASE WHEN date = '20190901' THEN amount ELSE 0 END) AmountFromSept01,
SUM(CASE WHEN date = '20191001' THEN amount ELSE 0 END) AmountFromOct01
FROM CTE
GROUP BY id;
However, some people have tested for performance and found that pre-aggregating can improve performance.
If I understand you correctly, then you're just trying to pivot, but only with two particular dates:
select id,
date1 = sum(iif(date = '2000-01-01', amount, null)),
date2 = sum(iif(date = '2000-01-02', amount, null))
from [table]
group by id

compare two different date ranges sales in two columns

I want to compare two different date ranges sales in two columns.. I am using query below but its giving wrong sales.. please correct my query
select s1.Itm_cd,s1.Itm_Name,Sum(S1.amount),Sum(s2.amount)
from salestrans s1,salestrans s2
where s1.Itm_cd = S2.Itm_cd
and S1.Tran_dt between '20181101' and'20181130'
and S2.Tran_dt between '20171101' and '20171130'
group by s1.Itm_cd,s1.Itm_Name
Order by s1.Itm_cd
I suspect that you want conditional aggregation here:
WITH cte AS (
SELECT
s1.Itm_cd,
s1.Itm_Name,
SUM(CASE WHEN s1.Tran_dt BETWEEN '20181101' AND '20181130'
THEN s1.amount ELSE 0 END) AS sum_2018,
SUM(CASE WHEN s1.Tran_dt BETWEEN '20171101' AND '20171130'
THEN s1.amount ELSE 0 END) AS sum_2017
FROM salestrans s1
GROUP BY
s1.Itm_cd,
s1.Itm_Name
)
SELECT
Itm_cd,
Itm_Name,
sum_2018,
sum_2017,
CASE WHEN COALESCE(sum_2017, 0) <> 0
THEN FORMAT(100.0 * (sum_2018 - sum_2017) / sum_2017, 'N', 'en-us')
ELSE 'NA' END AS growth_pct
FROM cte
ORDER BY
Itm_cd;
Please try the following
select s1.Itm_cd,s1.Itm_Name,Sum(S1.amount),Sum(s2.amount)
from salestrans s1,salestrans s2
where s1.Itm_cd = S2.Itm_cd
and Convert(Varchar(10),S1.Tran_dt,112) between '20181101' and'20181130'
and Convert(Varchar(10),S2.Tran_dt,112) between '20171101' and '20171130'
group by s1.Itm_cd,s1.Itm_Name
Order by s1.Itm_cd
Here the logic is that in right side while comparision you are providing only date and not any separator and time. The same way should be applied to the column in left side for comparision.
if(Convert(Varchar(10), getdate(),112) = '20181224')
print 'Matched'
else
print 'Not Matched'
if(getdate() = '20181224')
print 'Matched'
else
print 'Not Matched'
Here the output is Matched for first and Not Matched because in first case both side same format has been taken for comparison.