Pivot Different Prices for the Same Item - sql

I have a need to show different prices for the same product where the client wants to understand discrepancies in same region. The source table looks like below
Item
Brand
Concept
Price
00A
A
Alpha
1
00B
A
Alpha
1
00B
A
Alpha
2
00B
A
Beta
3
00A
B
Alpha
1
00B
B
Alpha
1
00B
B
Beta
2
00B
B
Alpha
3
The output I am trying to achieve is a little complicate but can be simplified if we only focus on Brand A so please consider i am pivoting for Brand A only. Result Needed is
Item
Alpha
Beta
00A
1
Null
Null
00B
1
2
3

Are you looking for conditional aggregation?
select item, brand,
max(case when concept = 'Alpha' and seqnum = 1 then price end) as alpha_price_1,
max(case when concept = 'Alpha' and seqnum = 2 then price end) as alpha_price_2,
max(case when concept = 'Beta' and seqnum = 1 then price end) as alpha_price_3
from (select t.*,
row_number() over (partition by item, brand, concept order by price) as seqnum
from t
) t
group by item, brand;

Related

query a table with multiple rows for same id, into single data row in results

I have a few tables like this where a person has multiple data rows. The IDs are sequential but do not always start at 1. Is there a way to have the results come out in a single data row for each person. I have a few tables like this and I ultimately would like to join them via CLIENT_ID, but I'm a bit stumped. Is this possible?
Using oracle sql.
CLIENT_ID
NAME
ID
ID_DESCRIPTION
5
joe
1
apple
5
joe
5
orange
68
brian
2
orange
68
brian
6
mango
68
brian
10
lemon
12
katie
3
watermelon
where the results look like this
CLIENT_ID
NAME
ID1
ID1_DESCRIPTION
ID2
ID2_DESCRIPTION
ID3
ID3_DESCRIPTION
5
joe
1
apple
5
orange
68
brian
2
orange
6
mango
10
lemon
12
katie
3
watermelon
If Pivot ist not available, this should do it:
Select
Client_id,
sum(case when id_description='apple' then 1 else 0 end) as Apples,
sum(case when id_description='orange' then 1 else 0 end) as Oranges...
[]etc.
from
t
group by Client_ID
Might need some minor tweaking as I wrote this just off the top of my head, but something like this should work. Will say this doesn't account for more than 3 rows per CLIENT_ID. For that, would need to do a dynamic pivot (plenty of online articles on this topic).
Pivoting Based on Order of Items
WITH cte_RowNum AS (
SELECT ROW_NUMBER() OVER (PARTITION BY CLIENT_ID ORDER BY ID) AS RowNum
,*
FROM YourTable
)
SELECT CLIENT_ID
,MAX(CASE WHEN RowNum = 1 THEN ID END) AS ID1
,MAX(CASE WHEN RowNum = 1 THEN [Description] END) AS ID1_DESCRIPTION
,MAX(CASE WHEN RowNum = 2 THEN ID END) AS ID2
,MAX(CASE WHEN RowNum = 2 THEN [Description] END) AS ID2_DESCRIPTION
,MAX(CASE WHEN RowNum = 3 THEN ID END) AS ID3
,MAX(CASE WHEN RowNum = 3 THEN [Description] END) AS ID3_DESCRIPTION
FROM cte_RowNum
GROUP BY CLIENT_ID;

We need to provide rank. Logic is whenever we have a value 'Product' then we must start the new number & all other below should follow the same rank

Sample Input:
ID
Vals
1
Product
2
Milk
3
Butter
4
Cheese
5
Yogurt
6
Product
7
Muesli
8
Porridge
9
Product
10
Banana
Sample Output:
ID
Vals
RANK
1
Product
1
2
Milk
1
3
Butter
1
4
Cheese
1
5
Yogurt
1
6
Product
2
7
Muesli
2
8
Porridge
2
9
Product
3
10
Banana
3
This looks like a conditional cumulative sum:
select t.*,
sum(case when vals = 'Product' then 1 else 0
end) over (order by id) as ranking
from t
order by id;
you also can use window function:
SELECT * , SUM(CASE WHEN Vals ='Product' THEN 1 END) OVER (ORDER BY id) ranking
FROM tableName
Assuming your table is sorted by ID:
SELECT T.ID,
T.Vals,
(SELECT COUNT(DISTINCT ID) FROM table WHERE Vals = 'Product' AND ID <= T.ID) as Rank
FROM table T

Getting unique Ids but not loose any data using SQL

Given a table sale where id is not unique:
id name item quantity
1 Darsh shoes 5
2 Liyah oil 1
2 Eiliyah watch 1
3 Zakaria notebook 2
3 Elliot shirt 3
4 Reese bag 1
I need to select all unique ids for a row and not loose any data(like for id in (2,3) where both name,item and quantity should be displayed in same row).Also there are maximum of 2 same id in sale table.
I tried using row_number() to get some unique pattern(s).
From this query :
Select a.id,a.name,a.item,a.quantity,b.name as name2,b.item as item2,b.quantity as quantity2
,row_number() over(partition by a.id order by a.id) as f1
,row_number() over(partition by a.name order by a.id) as f2
from sale a inner join sale b on a.id = b.id
I got this
id name item quantity name2 item2 quantity2 f1 f2
1 Darsh shoes 5 Darsh shoes 5 1 1
2 Eiliyah watch 1 Liyah oil 1 2 1
2 Eiliyah watch 1 Eiliyah watch 1 4 2
3 Elliot shirt 3 Zakaria notebook 2 2 1
3 Elliot shirt 3 Elliot shirt 3 4 2
2 Liyah oil 1 Eiliyah watch 1 3 1
2 Liyah oil 1 Liyah oil 1 1 2
4 Reese bag 1 Reese bag 1 1 1
3 Zakaria notebook 2 Elliot shirt 3 3 1
3 Zakaria notebook 2 Zakaria notebook 2 1 2
Now here the problem,If I filter f1,f2 and use IIF for remove repetitive data using this query :
Select id,name,item,quantity
,iif(name = name2,NULL,name2) as name2
,iif(item = item2,NULL,item2) as item2
,iif(quantity = quantity2,NULL,quantity2) as quantity2
from (
Select a.id,a.name,a.item,a.quantity,b.name as name2,b.item as item2,b.quantity as quantity2
,row_number() over(partition by a.id order by a.id) as f1
,row_number() over(partition by a.name order by a.id) as f2
from sale a inner join sale b on a.id = b.id
)t
where (f1=1 and f2=1) or(f1=3 and f2=1)
order by id
then quantity2 is (null) in 2nd row as shown below.
id name item quantity name2 item2 quantity2
1 Darsh shoes 5 NULL NULL NULL
2 Liyah oil 1 Eiliyah watch NULL
3 Zakaria notebook 2 Elliot shirt 3
4 Reese bag 1 NULL NULL NULL
So, there can be same quantity for different item and name.
Expected result:
id name item quantity name2 item2 quantity2
1 Darsh shoes 5 NULL NULL NULL
2 Liyah oil 1 Eiliyah watch 1
3 Zakaria notebook 2 Elliot shirt 3
4 Reese bag 1 NULL NULL NULL
Please help me.
Thanks!
One method is conditional aggregation . . . if you know that there are at most two duplicates per id:
select id,
max(case when seqnum = 1 then name end) as name_1,
max(case when seqnum = 1 then item end) as item_1,
max(case when seqnum = 1 then quantity end) as quantity_1,
max(case when seqnum = 2 then name end) as name_2,
max(case when seqnum = 2 then item end) as item_2,
max(case when seqnum = 2 then quantity end) as quantity_2
from (select s.*,
row_number() over (partition by id order by id) as seqnum
from sale s
) s
group by id;
As per your expected result .You can create temp(or Intermediate table) and as there are maximum of same two id ,then this can be your answer:
select *,row_number() over (partition by id order by id) as u_id into #test from sale
select * from (select * from #test where u_id=1) a
left join (select * from #test where u_id=2)b
on a.id = b.id

Merging multiple rows into one using Postgresql

I am trying to combine multiple rows with the same IDs to one.
My raw table looks like this:
ID | person_id | eur_amount
1 3 200
1 2 100
2 3 80
2 2 100
The output should look like this:
ID | person_1 | eur_amount_1 | person_2 | eur_amount_2 |
1 3 200 2 100
2 3 80 2 100
The max number of persons is the same. I already tried solving it with a multiple JOIN statements and the crosstab() function as mentioned here PostgreSQL Crosstab Query.
But I couldn't find a solution for this - does anyone know a good way to achive the desired output?
Thanks in advance!
You can do this using cross tab or conditional aggregation. But you need to identify the rows, using row_number(). For instance:
select id,
max(case when seqnum = 1 then person_id end) as person_id_1,
max(case when seqnum = 1 then eur_amount end) as eur_amount_1,
max(case when seqnum = 2 then person_id end) as person_id_2,
max(case when seqnum = 2 then eur_amount end) as eur_amount_2
from (select t.*,
row_number() over (partition by id order by id) as seqnum
from t
) t
group by id;

SQL convert rows to columns with static headers

I have a data set that I need to transform from rows to columns.
I looked at pivot and does not really answer the problem since I need specific static column headers (not matching the data names).
Here is how the current data is stored:
Id | SpCode
-------------------------
1 AA
1 BB
1 CC
2 FF
2 LL
3 TT
3 YY
3 ZZ
3 XX
4 AA
4 BB
5 AA
6 WW
6 MM
6 PP
I need to display it like this.
I will never have more than 5 columns and would like to keep the column name static so I can join and refer to it easily.
ID SpCode1 |SpCode2 | SpCode3 | SpCode4 | SpCode5
1 AA |BB | CC
2 FF |LL
3 TT |YY |ZZ |XX
4 AA |BB
5 AA
6 WW |MM |PP
Much appreciated for any help.
PS: using SQL Server 2014
Thanks
Oren
One method is pivot. Another is conditional aggregation. I find the latter easier to use:
select id,
max(case when seqnum = 1 then spcode end) as spcode_1,
max(case when seqnum = 2 then spcode end) as spcode_2,
max(case when seqnum = 3 then spcode end) as spcode_3,
max(case when seqnum = 4 then spcode end) as spcode_4,
max(case when seqnum = 5 then spcode end) as spcode_5
from (select t.*,
row_number() over (partition by id order by spcode) as seqnum
from t
) t
group by id;