Oracle SQL : Pivot a column - sql

I have table structure like below :
product supplier price qty
------- -------- ----- ---
SOAP ABC 50 10
SOAP DCE 50 10
BRUSH FGH 30 5
I would like to transform this table into :
product supplier_1 supplier_2 price qty
------- -------- ---------- ----- ---
SOAP ABC DCE 50 10
BRUSH FGH 30 5
how can I do it in SQL? thanks in advance.

Maybe this helps:
select product,
max(case when rn = 1 then supplier end) as supplier_1,
max(case when rn = 2 then supplier end) as supplier_2,
-- ...
-- max(case when rn = n then supplier end) as supplier_n,
avg(price) as price,
sum(qty) as sum
from(select t.*,
row_number() over (partition by product order by supplier) rn
from your_table t
)
group
by product;

select product,supplier_1,supplier_2,price,qty from table
model
return all rows
dimension by(product)
measures(supplier,
lpad(' ',10) supplier_1,
lpad(' ',10) supplier_2
)
rules upsert(
supplier_1[0] = supplier['SOAP'],
supplier_2[0] = supplier['BRUSH']
)
10G or 10G above available.

Related

DB2 Toad SQL - Group by Certain Columns using Max Command

I am having some trouble with the below query. I do understand I need to group by ID and Category, but I only want to group by ID while keeping the rest of the columns based on Rank being max. Is there a way to only group by certain columns?
select ID, Category, max(rank)
from schema.table1
group by ID
Input:
ID Category Rank
111 3 4
111 1 5
123 5 3
124 7 2
Current Output
ID Category Rank
111 3 4
111 9 1
123 5 3
124 7 2
Desired Output
ID Category Rank
111 1 5
123 5 3
124 7 2
You can use:
select *
from table1
where (id, rank) in (select id, max(rank) from table1 group by id)
Result:
ID CATEGORY RANK
---- --------- ----
111 1 5
123 5 3
124 7 2
Or you can use the ROW_NUMBER() window function. For example:
select *
from (
select *,
row_number() over(partition by id order by rank desc) as rn
from table1
) x
where rn = 1
See running example at db<>fiddle.
You can try using - row_number()
select * from
(
select ID, Category,rank, row_number() over(partition by id order by rank desc) as rn
from schema.table1
)A where rn=1

How to use this in sql -- > max(sum (paid * quantity )) to solve a query

How to get the max value order of each customer ?
select num, max(sum(paid*quantity))
from orders join
pizza
using (order#)
group by customer#;
table
num orderN price
-------- --- -------
1 109 30
1 118 25
3 101 30
3 115 27
4 107 23
5 100 17
5 129 16
output req-
num Pnum price
-------- --- -------
1 109 30
3 101 30
4 107 23
5 100 17
You want to select the record having the highest price in each group of nums.
If your RDBMS supports window functions, that's straight forward with ROW_NUMBER() :
SELECT num, pnum, price
FROM (
SELECT t.*, ROW_NUMBER OVER(PARTITION BY num ORDER BY price DESC) rn
FROM mytable t
) x
WHERE rn = 1
Else, you can take the following approach, that uses a NOT EXISTS condition with a correlated subquery to ensure that the record being joined in the one with the highest price for the current num :
SELECT num, pnum, price
FROM mytable t
WHERE NOT EXISTS (
SELECT 1 FROM mytable t1 WHERE t1.num = t.num AND t1.price > t.price
)

Get latest 2 records from table

I have a SQL Server table like this
ProdID Code
-------- ------
1001 A
2001 B
1001 C
3001 D
3001 E
1001 F
1001 Z
2001 G
2001 H
3001 I
4001 J
I am expecting output as
ProdID Code
-------- ------
1001 Z
1001 F
2001 H
2001 G
3001 I
3001 E
Only to show latest 2 data. If any id has less than 2 data I don't want to show it (like ProdID 4001).
Try this
;With cte As
(Select ProdID, Code, Row_Number() Over(Partition By ProdID Order By Code Desc) As rn,
Count(*) Over(Partition By ProdID) As NbrRows
From mytable)
Select ProdID, Code
From cte
Where rn <= 2 And NbrRows > 1
Order By ProdID, Code desc;
sql fiddle demo
Using ROW_NUMBER and COUNT:
SQL Fiddle
;WITH cte AS(
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY ProdID ORDER BY Code DESC),
cnt = COUNT(*) OVER(PARTITION BY ProdID)
FROM tbl
)
SELECT
ProdID, Code
FROM cte
WHERE
rn <= 2
AND cnt >= 2

SQL group by with NULL

I have a table something like this:
ID ProductID ProductName Price
== ========= =========== =====
1 XX1 TShirt 10
2 XX1 TShirt 10
3 NULL TShirt 10
4 XX2 Shirt 20
5 XX3 Shirt1 30
Now I want this to group by ProductName and results will be as follows
ID ProductID ProductName Price
== ========= =========== =====
1 XX1 TShirt 30
4 XX2 Shirt 20
5 XX3 Shirt1 30
Thanks
ProductID seems to be irrelevant for the group, so don't use it. To get all columns you could use a CTE and a ranking function like ROW_NUMBER:
WITH CTE AS(
SELECT ID,
ProductID,
ProductName,
Price = SUM(Price) OVER (PARTITION BY ProductName),
RN = ROW_NUMBER() OVER (PARTITION BY ProductName ORDER BY ID)
FROM dbo.TableName
)
SELECT CTE.* FROM CTE
WHERE RN = 1
If you want to take the row which contains the ProductID(where it is not NULL) modify the ORDER BY:
WITH CTE AS(
SELECT ID,
ProductID,
ProductName,
Price = SUM(Price) OVER (PARTITION BY ProductName),
RN = ROW_NUMBER() OVER (PARTITION BY ProductName
ORDER BY CASE WHEN ProductID IS NOT NULL
THEN 0 ELSE 1 END, ID)
FROM dbo.TableName
)
SELECT CTE.* FROM CTE
WHERE RN = 1

Partial pivot without pivot operator

I am looking for a query to partially pivot a table without using the PIVOT operator (old ms-sql server).
the table:
id-------item---------rank1---------rank2
231------it1--------- 1 ----------- 1
231------it2-------- 1 ----------- 2
231------it3--------- 1 ----------- 3
154------it4--------- 3 ----------- 4
154------it2--------- 1 ----------- 2
155------it2--------- 1 ----------- 2
156------it3 -------- 2 ----------- 2
156------it1 -------- 1 ----------- 1
expected result:
id---------item1----item2----item3---item*...
231 -------it1------it2---------it3
154--------it2------it4
155--------it2
156--------it1------it3
order by rank1 and rank2
I searched on google but the solution I found was too complicated to apply.
In SQL Server, you could use row_number to assign a row number for each id group. Then you can use the max(case(... trick to pivot:
select id
, max(case when rn = 1 then item end) as item1
, max(case when rn = 2 then item end) as item2
, max(case when rn = 3 then item end) as item3
from (
select row_number() over (partition by id
order by rank1, rank2) as rn
, *
from YourTable
) as SubQueryAlias
group by
id
There is no general solution for N items without using dynamic SQL.