JOIN always the default value, else join the match value - sql

I have the following SQL Server Query
select r.isactive,r.workingyear,r.startperiod,r.endperiod,r.anniversary
from setup_holiday_policy t cross apply
(select data
from dbo.Split(t.scheduleapplication, ',')
) di cross apply
(select max(case when did.id = 1 then did.data end) as isactive,
max(case when did.id = 2 then did.data end) as workingyear,
max(case when did.id = 3 then did.data end) as anniversary,
max(case when did.id = 4 then did.data end) as startperiod,
max(case when did.id = 5 then did.data end) as endperiod
from dbo.Split(di.data,':') did
) r
WHERE r.workingyear = #employeeworkingyears
The policy table can have a 0 value in the workingyear field. Meaning that when this field has 0 then is the default record I should return.
setup_holiday_policy
So, if #employeeworkingyears = 2 and there is no workingyears = 2 in setup_holiday_policy I should return the default row that has the 0 value in workingyears field.
This is a sample of the rows returned.
Any clue how to achieve this?

If only one row is going to be returned (as suggested by the sample data), you can do this using top:
select top 1 r.isactive,r.workingyear,r.startperiod,r.endperiod,r.anniversary
from setup_holiday_policy t cross apply
(select data
from dbo.Split(t.scheduleapplication, ',')
) di cross apply
(select max(case when did.id = 1 then did.data end) as isactive,
max(case when did.id = 2 then did.data end) as workingyear,
max(case when did.id = 3 then did.data end) as anniversary,
max(case when did.id = 4 then did.data end) as startperiod,
max(case when did.id = 5 then did.data end) as endperiod
from dbo.Split(di.data,':') did
) r left outer join
(select #employeeworkingyears as employeeworkingyears
) e
on
WHERE r.workingyear in (#employeeworkingyears, 0)
order by r.workingyear desc;

Related

How to pivot row data into specific columns db2

I would like to pivot results from a table into a new structure. So that it can map all the children to the parent product.
Current Result
Parent_Prod_Num|Child_Prod_Num|Child_Prod_Code|Child_Prod_Name
1|11|a123|a
1|12|b123|ab
1|13|c123|abc
Expected Result
Parent_Prod_Num|Child_Prod_Num_1| Child_Prod_Code_1|Child_Prod_Name_1| Child_Prod_Num_2| Child_Prod_Code_2|Child_Prod_Name_2| Child_Prod_Num_3| Child_Prod_Code_3|Child_Prod_Name_3
1|11|a123|a|12|b123|ab|13|c123|abc
For a fixed maximum number of children per parent, you can enumerate the rows with row_number(), then pivot with conditional aggregation:
select parent_prod_num,
max(case when rn = 1 then child_prod_num end) as child_prod_num_1,
max(case when rn = 1 then child_prod_code end) as child_prod_code_1,
max(case when rn = 1 then child_prod_name end) as child_prod_name_1,
max(case when rn = 2 then child_prod_num end) as child_prod_num_2,
max(case when rn = 2 then child_prod_code end) as child_prod_code_2,
max(case when rn = 2 then child_prod_name end) as child_prod_name_2,
max(case when rn = 3 then child_prod_num end) as child_prod_num_3,
max(case when rn = 3 then child_prod_code end) as child_prod_code_3,
max(case when rn = 3 then child_prod_name end) as child_prod_name_3
from (
select t.*, row_number() over(partition by parent_prod_num order by child_prod_num) rn
from mytable t
) t
group by parent_prod_num

SQL Server Query with join and merge two row into single row of record

I have had a sample table like these
I would like to have a final result for my query in this way
I have no clue how to create SQL Server Query to archive the result as said about. Would you mind to guide me how to make it works?
Regards,
Assuming you have at most two rows, you can use row_number() to enumerate the values and conditional aggregation (or pivot, if you prefer):
select m.movementid, m.arrflt, m.depflt,
sum(case when seqnum = 1 then des else 0 end) as des_1,
sum(case when seqnum = 1 then cargo else 0 end) as cargo_1,
sum(case when seqnum = 1 then mail else 0 end) as mail_1,
sum(case when seqnum = 1 then luggage else 0 end) as luggage_1,
sum(case when seqnum = 2 then des else 0 end) as des_2,
sum(case when seqnum = 2 then cargo else 0 end) as cargo_2,
sum(case when seqnum = 2 then mail else 0 end) as mail_2,
sum(case when seqnum = 2 then luggage else 0 end) as luggage_2
from movement m join
(select md.*,
row_number() over (partition by movementid order by movementid) as seqnum
from movementdetail md
) md
on md.movementid = m.movementid
group by m.movementid, m.arrflt, m.depflt;

(store procedure) combine result 2 rows into 1 row result

can i combine result row 3 and row 4 into 1 row record?
select #fYear as [Year],
(case when main.Description in ('Kecil', 'Tanah') then 'JK'
else main.Description
end) as description,
--CardType,
sum(case when MONTH(blue.AppliedDate) = 1 then 1 else 0 end) as Jan_Collection,
sum(case when MONTH(blue.AppliedDate) = 2 then 1 else 0 end) as Feb_Collection,
...
from tblR as main
left join tblP as b on main.requestorid = b.requestorid
left join tblB as blue on b.partyid = blue.partyid and YEAR(blue.AppliedDate) = #fYear
group by (case when main.Description in ('Kecil', 'Tanah') then 'JK'
else main.Description
end)
this output like:
https://gyazo.com/d930cb2aee92f90ba31dd543d6ca64f3
but can i display combine record row 3 and 4 into 1 record like JK like this picture: https://gyazo.com/a89ed2fa04b51135bf8601d59d4af0b2
Thanks.
If you want to combine those specific descriptions, you can use a case, both in the select and the group by:
select #fYear as [Year],
(case when description in ('kecil', 'Tanah') then 'JK'
else main.Description
end) as Description,
sum(case when MONTH(blue.AppliedDate) = 1 then 1 else 0 end) as Jan_Collection,
sum(case when MONTH(blue.AppliedDate) = 2 then 1 else 0 end) as Feb_Collection,
...
from tblR main left join
tblP b
on main.requestorid = b.requestorid left join
tblB
blue
on b.partyid = blue.partyid and YEAR(blue.AppliedDate) = #fYear
group by (case when description in ('kecil', 'Tanah') then 'JK'
else main.Description
end)

How to make multiple rows into columns

I've tried MAX CASE WHEN and CTE but for some reason can't exactly figure this out.
My data looks like this:
SELECT RC, isMHy, eligible
FROM test
RC isMHY eligible
190B05 0 1
190K00 1 0
There can be up to 4 rows in the table, I want to the results to look like this (12 columns in case there are 4 rows)
RC1 isMHY1 eligible1 RC2 isMHY2 eligible2
190B05 0 1 190K00 1 0
Any suggestions would be appreciated
You can use conditional aggregation with ROW_NUMBER() :
SELECT MAX(CASE WHEN s.rnk = 1 THEN s.rc END) as rc1,
MAX(CASE WHEN s.rnk = 1 THEN s.ismhy END) as ismhy1,
MAX(CASE WHEN s.rnk = 1 THEN s.eligible END) as eligible1,
MAX(CASE WHEN s.rnk = 2 THEN s.rc END) as rc2,
MAX(CASE WHEN s.rnk = 2 THEN s.ismhy END) as ismhy2,
MAX(CASE WHEN s.rnk = 2 THEN s.eligible END) as eligible2,
..........
FROM(
SELECT t.*,
ROW_NUMBER() OVER(ORDER BY SELECT 1) as rnk
FROM test t) s

How to use count distinct along multiple columns?

Input:
id sem1 sem2 sem3 sem4 sem5 sem6 sem7
1 S O S R null null null
2 O O R R S null null
Desired Output:
id O R S
1 1 1 2
2 2 2 1
If your database supports APPLY/UNPIVOT operator then use this
CROSS APPLY method
SELECT id,
SUM(CASE WHEN val = 'O' THEN 1 ELSE 0 END) O,
SUM(CASE WHEN val = 'R' THEN 1 ELSE 0 END) R,
SUM(CASE WHEN val = 'S' THEN 1 ELSE 0 END) S
FROM mytable
CROSS apply (VALUES (sem1),
(sem2),
(sem3),
(sem4),
(sem5),
(sem6),
(sem7)) cs(val)
GROUP BY id
SQL FIDDLE DEMO
UNPIVOT method
SELECT id,
SUM(CASE WHEN val = 'O' THEN 1 ELSE 0 END) O,
SUM(CASE WHEN val = 'R' THEN 1 ELSE 0 END) R,
SUM(CASE WHEN val = 'S' THEN 1 ELSE 0 END) S
FROM (SELECT *
FROM mytable) a
UNPIVOT (val
FOR col IN ( sem1,
sem2,
sem3,
sem4,
sem5,
sem6,
sem7 )) upv
GROUP BY id
SQL FIDDLE DEMO
I personally prefer CROSS APPLY method over UNPIVOT since it is more readable. Performance wise both will be identical