(HANA SQL) Show multiple values in one row - sql

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

Related

Displaying a multiple columns in single row in 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

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 join a table to itself using rank multiple times?

I apologize if there is an existing solution, I tried searching quite a bit but couldnt find much.
Here's what I am trying to do:
I have a table that resembles the first image. I want it to look like the second image. Basically every time rnk_address = 1, I want that row's order_date to be moved into a separate column for that associated user_id.
I'm ultimately trying to calculate the average difference in order_date between all rnk_address = 1, by user_id.
I added a user_counter column using rank because I imagine I will need to do some time of join where i do user_rank = user_rank + 1? But not sure....
Original table:
End result:
You can use conditional aggregation:
select user_id, first_name,
max(case when seqnum = 1 then order_date end) as order_date_1,
max(case when seqnum = 2 then order_date end) as order_date_2,
max(case when seqnum = 3 then order_date end) as order_date_3
from (select t.*,
row_number() over (partition by user_id order by order_date) as seqnum
from t
where rnk_address = 1
) t
group by user_id, first_name;

SQL Group up rows data into one row

I have data in a table like this:
I want to organise the table data so that I can get a maximum of 3 letters per row grouped by account number.
Below would be the result I want:
I can use dense rank to group up the account numbers but not sure how to get the data I want in the format above.
Logic:
There are 4 letters for account 123. Final result groups by account number with first 3 letters as you can only have a maximum of 3 letters per row. The fourth letter must go on the second row.
Here's one option using conditional aggregation, first creating a row_number, and then creating a row grouping using every 3 rows with % (modulus operator):
select account_number,
max(case when rn % 3 = 1 then letter end) as letter1,
max(case when rn % 3 = 2 then letter end) as letter2,
max(case when rn % 3 = 0 then letter end) as letter3
from (
select *, row_number() over (partition by account_number, rn % 3 order by rn) newrn
from (
select *, row_number() over (partition by account_number order by letter) rn
from yourtable
) t
) y
group by account_number, newrn
order by account_number
Online Demo
I would do this with only one call to row_number():
select account_number,
max(case when seqnum % 3 = 1 then letter end) as letter_a,
max(case when seqnum % 3 = 2 then letter end) as letter_b,
max(case when seqnum % 3 = 0 then letter end) as letter_c
from (select t.*,
row_number() over (partition by account_number order by letter) as seqnum
from t
) t
group by account_number, floor( (seqnum - 1) / 3)
order by account_number, min(seqnum);