Displaying a multiple columns in single row in SQL - sql

SELECT * FROM
(select ID,POLICY_ID,CONTACT_ID,POLICY_CONTACT_ROLE,ROW_NUMBER () OVER (PARTITION BY POLICY_ID,POLICY_CONTACT_ROLE ORDER BY ID ) AS ORDERNO
FROM P_POL_HEADER_CONTACT ) SUB
WHERE SUB.ORDERNO=1 AND POLICY_ID =20001
I want to arrange the above query to take result like this
Thanks

You need to pivot on a row-number.
You can use PIVOT, but I often find a simple GROUP BY/MAX is simpler, especially when you need to rename the columns.
SELECT
SUB.POLICY_ID
,MAX(CASE WHEN POLICY_CONTACT_ROLE_NO = 1 THEN POLICY_CONTACT_ROLE END) AS POLICY_CONTACT_ROLE
,MAX(CASE WHEN POLICY_CONTACT_ROLE_NO = 2 THEN POLICY_CONTACT_ROLE END) AS POLICY_CONTACT_ROLE2
,MAX(CASE WHEN POLICY_CONTACT_ROLE_NO = 3 THEN POLICY_CONTACT_ROLE END) AS POLICY_CONTACT_ROLE3
-- etc etc
FROM (
SELECT *,
ROW_NUMBER () OVER (PARTITION BY POLICY_ID ORDER BY POLICY_CONTACT_ROLE) AS POLICY_CONTACT_ROLE_NO
FROM (
SELECT *
ROW_NUMBER () OVER (PARTITION BY POLICY_ID, POLICY_CONTACT_ROLE ORDER BY ID ) AS ORDERNO
FROM P_POL_HEADER_CONTACT
WHERE POLICY_ID = 20001
) SUB
WHERE SUB.ORDERNO = 1
) SUB
GROUP BY SUB.POLICY_ID

You want conditional aggregation. I think the logic you want is:
SELECT PCH.POLICY_ID,
MAX(CASE WHEN SEQNUM = 1 THEN POLICY_CONTACT_ROLE END) as POLICY_CONTACT_ROLE_1,
MAX(CASE WHEN SEQNUM = 2 THEN POLICY_CONTACT_ROLE END) as POLICY_CONTACT_ROLE_2,
MAX(CASE WHEN SEQNUM = 3 THEN POLICY_CONTACT_ROLE END) as POLICY_CONTACT_ROLE_3
FROM (SELECT PHC.*,
ROW_NUMBER() OVER (PARTITION BY POLICY_ID ORDER BY ID ) AS SEQNUM
FROM P_POL_HEADER_CONTACT PHC
) PHC
WHERE POLICY_ID = 20001
GROUP BY POLICY_ID;
I'm not sure what your filtering on ORDERNO is really doing. If you have duplicates, use DENSE_RANK() instead of ROW_NUMBER(). However, without knowing what your data looks like, I am guessing that is unnecessary.

Exclude CONTACT_ID from query. And use STUFF query to convert your rows into columns

Related

SQL to find records with last 3 same status

I have the following tasks table:
id type submit_time status
I need to run a query that returns only the types which their last 3 tasks finished with status "FAILED".
How can I do this?
Should I use a window function?
Thanks
You can use aggregation and filtering after using row_number() to get the last three rows:
select type
from (select t.*,
row_number() over (partition by type order by submit_time desc) as seqnum
from t
) t
where seqnum <= 3
group by type
having min(status) = max(status) and min(status) = 'FAILED' and
count(*) = 3;
Actually, a slightly simpler method is:
select type
from (select t.*,
row_number() over (partition by type order by submit_time desc) as seqnum
from t
) t
where seqnum <= 3 and status = 'FAILED'
group by type
having count(*) = 3;

(HANA SQL) Show multiple values in one row

I am trying to complete the following:
Old situation
What I want
For a fixed maximum number of target columns, you can use window functions and conditional aggregation:
select customer,
max(case when rn = 1 then order_date end) as order_date_1,
max(case when rn = 2 then order_date end) as order_date_2,
max(case when rn = 3 then order_date end) as order_date_3
from (
select t.*, row_number() over(partition by customer order by order_date) rn
from mytable t
) t
group by customer

Split Record into multiple column after Row_number and Partition By

I want to have my result to be displayed in 4 columns.
This is how I did my coding.
SELECT T.MT_CARD_TYP_ID,
ROW_NUMBER() OVER (PARTITION BY T.APP_ID ORDER BY T.DT_CREATE) AS RN
FROM T_CS_FAC_CC T
WHERE app_id = '8F9A97B0CB5349429C44F15830EDC18F';
What should I do the next step? Can someone pro help me out please?
This is how my result look
This is how I want the result look like.
You can try to use condition aggravated function.
SELECT app_id,
MAX(CASE WHEN RN = 1 THEN MT_CARD_TYP_ID END),
MAX(CASE WHEN RN = 3 THEN MT_CARD_TYP_ID END),
MAX(CASE WHEN RN = 2 THEN MT_CARD_TYP_ID END),
MAX(CASE WHEN RN = 4 THEN MT_CARD_TYP_ID END)
FROM (
SELECT T.MT_CARD_TYP_ID, ROW_NUMBER() OVER(PARTITION BY T.APP_ID ORDER BY T.DT_CREATE) AS RN
FROM T_CS_FAC_CC T
where app_id='8F9A97B0CB5349429C44F15830EDC18F'
)t1
GROUP BY app_id

Organizing SQL data based on date

I am trying to organize my SQL data based off of the dates from which the orders were made.
My data:
SELECT DISTINCT ORDER_NO, ITEM, VERSION_NO,
(CASE WHEN ROW_NUMBER() OVER (PARTITION BY ORDER_NO ORDER BY NOT_BEFORE_DATE
ASC) = 1
THEN 'what-if'
ELSE 'wh'
END) AS VERSION_NEW
,
(CASE WHEN ROW_NUMBER() OVER (PARTITION BY ORDER_NO ORDER BY
NOT_BEFORE_DATE ASC) = 2
THEN 'initial'
ELSE 'other'
END) AS VERSION
FROM FDT_MAPTOOL
WHERE ITEM IN (1032711)
;
My results:
I want my data to be ordered by PO# and the date it was created.
As you can see in my picture the First two line have the same ITEM and same PO (Order_No). I need the first two to say Initial on the side because they are the first two based on the dates. They were created first. Everything after should say other.
I am not sure if PL/SQL is needed for this?
Thank you!
Use a different analytic function so that more than one row can have the value of 1 e.g.
SELECT DISTINCT ORDER_NO, ITEM, VERSION_NO,
(CASE WHEN DENSE_RANK() OVER (PARTITION BY ORDER_NO ORDER BY NOT_BEFORE_DATE
ASC) = 1
THEN 'what-if'
ELSE 'wh'
END) AS VERSION_NEW
,
(CASE WHEN DENSE_RANK() OVER (PARTITION BY ORDER_NO ORDER BY
NOT_BEFORE_DATE ASC) = 1
THEN 'initial'
ELSE 'other'
END) AS VERSION
FROM FDT_MAPTOOL
WHERE ITEM IN (1032711)
;
Either rank() OR dense_rank() should work here instead of row_number()
nb: note sure if you really need "select distinct"

How to improve Using RANK() top 2 results into unique columns

Here is the SQL 9(i) code written to show results 1 and 2 in their own columns. Is there a more efficient way to write this?
select
sc1.COIL as COIL1
, sc1.DEFECT as DEFECT1
, sc2.DEFECT as DEFECT2
FROM
(select
COIL, DEFECT
, RANK() OVER(PARTITION BY COIL ORDER BY WEIGHT DESC) RNK
from NOVELIS.F406, NOVELIS.F408 where F406_DEFECT_CODE = F408_REJECT_CODE
GROUP BY COIL, DEFECT
)sc1
, (select
COIL, DEFECT
, RANK() OVER(PARTITION BY COIL ORDER BY WEIGHT DESC) RNK
from NOVELIS.F406, NOVELIS.F408 where F406_DEFECT_CODE = F408_REJECT_CODE
GROUP BY COIL, DEFECT
)sc2
WHERE
sc1.RNK = 1
and sc2.RNK = 2
and sc1.COIL = sc2.COIL
You can use conditional aggregation and use 1 derived table
SELECT sc1.COIL AS COIL1,
MAX(CASE WHEN RNK = 1 THEN sc1.DEFECT END) AS DEFECT1,
MAX(CASE WHEN RNK = 2 THEN sc1.DEFECT END) AS DEFECT2
FROM
(
SELECT COIL,
DEFECT,
RANK() OVER(PARTITION BY COIL ORDER BY WEIGHT DESC) RNK
FROM NOVELIS.F406
--practice using joins
INNER JOIN NOVELIS.F408 ON F406_DEFECT_CODE = F408_REJECT_CODE
--not sure you need the group by here
) sc1
GROUP BY sc1.COIL
To avoid reading the tables twice, just read them once and pivot out the results:-
select
coil,
max (case when rnk=1 then defect else null end) defect1,
max (case when rnk=2 then defect else null end) defect2
FROM (
select
COIL, DEFECT,
RANK() OVER(PARTITION BY COIL ORDER BY WEIGHT DESC) RNK
from NOVELIS.F406
inner join NOVELIS.F408 on F406_DEFECT_CODE = F408_REJECT_CODE
) sc
WHERE
sc.RNK <= 2
group by coil