unpivot row values into multiple columns - sql

I have the following with the following structure:
http://sqlfiddle.com/#!6/0e72e/8
CREATE TABLE Prices
(
Day date,
ProductName nVARCHAR(10),
Location nVARCHAR(10),
RegPrice1 float,
SalePrice1 float,
SalePrice2 float
)
INSERT INTO Prices VALUES ('6/24/2014', 'xbox', 'NewYork',30,20,10)
INSERT INTO Prices VALUES ('6/24/2014', 'xbox', 'London', 100,80,60)
INSERT INTO Prices VALUES ('6/24/2014', 'xbox', 'Singapore', 70,50,30)
INSERT INTO Prices VALUES ('6/24/2014', 'watch1','NewYork', 500,400,300)
INSERT INTO Prices VALUES ('6/24/2014', 'watch1','London', 1000,800,600)
INSERT INTO Prices VALUES ('6/24/2014', 'watch1','Singapore', 999,888,777)
I want to unpivot this table so it looks like:
Day Pr_Name PriceType NewYork London Singapore
2014-06-24 xbox RegPrice1 30 100 70
2014-06-24 xbox SalePrice1 20 80 50
2014-06-24 xbox SalePrice2 10 60 30
2014-06-24 watch1 RegPrice1 500 1000 999
2014-06-24 watch1 SalePrice1 400 800 888
2014-06-24 watch1 SalePrice1 300 600 777
I was able to unpivot one layer to get the NewYork column but I haven't been able to get the London and Singapore columns in place. I have tinkered with the code below to add London and Singapore but have not been successful. Do I simply keep unpivoting?
select Day, ProductName, PriceType, NewYork
from (select * from Prices ) as t
Unpivot
(
NewYork for PriceType in (RegPrice1, SalePrice1, SalePrice2)
) As unpvt

we can use CROSS APPLY to unpivot the prices and then apply PIVOT
SELECT
*
FROM
( select Day, ProductName, Location, col, value
from Prices
cross apply
(
select 'RegPrice1' , Prices.RegPrice1 union all
select 'SalePrice1', Prices.SalePrice1 union all
select 'SalePrice2', Prices.SalePrice2
) c (col, value)
) PD
PIVOT
( max(value) for Location in ([NewYork],[London],[Singapore])
)pvt

Related

Create pivot/wide table using postgresql return error

I have a table that look like this
rank
country
year
1
USA
2020
2
Austria
2020
3
China
2022
1
France
2021
2
Canada
2021
3
USA
2021
I want to make it into a wide table with the result as follows
rank
2020
2021
1
USA
France
2
Austria
Canada
3
China
USA
I tried to use CROSSTAB function from various resources on the internet with the code as follows:
CREATE EXTENSION IF NOT EXISTS tablefunc;
SELECT * FROM CROSSTAB (
'SELECT rank, country, year
FROM country_yearly') AS ct(rank int, 2020 varchar, 2021 varchar);
It doesn't work and gives me this message
ERROR: syntax error at or near "2020"
In crosstab, you need to user order by , and give the year column in double quotes
For filtering the year i used generate series.
CREATE EXTENSION IF NOT EXISTS tablefunc;
SELECT * FROM CROSSTAB (
'SELECT rank, year,country
FROM conyear order by 1,2' ,'SELECT g FROM generate_series(2020,2021) g')
AS ct(rank int, "2020" varchar, "2021" varchar);
CREATE TABLE conyear
(
rank int,
country varchar(300),
year int
);
INSERT INTO conyear (rank ,country ,year) VALUES ('1', 'USA', '2020');
INSERT INTO conyear (rank ,country ,year) VALUES ('2', 'Austria', '2020');
INSERT INTO conyear (rank ,country ,year) VALUES ('3', 'China', '2022');
INSERT INTO conyear (rank ,country ,year) VALUES ('1', 'France', '2021');
INSERT INTO conyear (rank ,country ,year) VALUES ('2', 'Canada', '2021');
INSERT INTO conyear (rank ,country ,year) VALUES ('3', 'USA', '2021');
The output ,(in you output you posted china is not present in the year 2020)
rank 2020 2021
1 USA France
2 Austria Canada
3 null USA

Filter Table results Self Join

Imagine a large table that contains receipt information. Since it holds so much data, you are required to return a subset of the data, excluding or consolidating rows where possible.
Here is the SQL and results table showing how the data should be returned.
create table table1
(RecieptNo smallint, Customer varchar(10), ReceiptDate date,
ItemDesc varchar(10), Amount smallint)
insert into table1 values
(100, 'Matt','2022-01-05','Ball', 10),
(101, 'Mark','2022-01-07','Hat', 20),
(101, 'Mark','2022-01-07','Jumper', -20),
(101, 'Mark','2022-01-14','Spoon', 30),
(102, 'Luke','2022-01-15','Fork', 15),
(102, 'Luke','2022-01-17','Spork', -10),
(103, 'John','2022-01-20','Orange', 13),
(103, 'John','2022-01-25','Pear', 12)
If there are rows on the same receipt where the negative and positive values cancel out, do not return either row.
If there is a receipt with a negative amount not exceeding positive amount, the negative amount should be deducted from positive line.
RecieptNo
Customer
ReceiptDate
ItemDesc
Amount
100
Matt
2022-01-05
Ball
10
101
Mark
2022-01-14
Spoon
30
102
Luke
2022-01-15
Fork
5
103
John
2022-01-20
Orange
13
103
John
2022-01-25
Pear
12
This is proving tricky, any ideas?
Based on table you provided, I suppose you want only row with the earliest date when you have multiple rows with same receipts which bring positive Amount after deduction.
;WITH cte AS (
SELECT *
, SUM( amount) OVER (PARTITION BY RecieptNo ORDER BY RecieptNo, ReceiptDate ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS ActualAmount
, ROW_NUMBER() OVER (PARTITION BY RecieptNo ORDER BY RecieptNo, ReceiptDate) AS rn
FROM table1)
SELECT RecieptNo, Customer, ReceiptDate, ItemDesc, ActualAmount
FROM cte
WHERE ActualAmount > 0 AND rn = 1
Read about window functions and cte's though.

How to PIVOT multiple columns using SQL Server

I just wrote a query (for SQL Server) that is returning this output:
VendorId
Category
FirstSaleDate
StoreId
1
Car
1/1/2021
12
1
Clothes
1/2/2021
13
1
Toys
1/3/2021
14
1
Food
1/4/2021
15
1
Others
1/5/2021
15
But I actually need the following output
VendorId
Car
StoreId_car
Clothes
StoreId_clothes
Toys
StoreId_toys
Food
StoreId_food
Others
StoreId_others
1
1/1/2021
12
1/2/2021
1/2/2021
1/3/2021
14
1/4/2021
15
1/5/2021
15
I am new to SQL Server, but I saw that this might be possible by using two PIVOTs. I really need your help to find the right syntax.
scenario and output
You just need to pivot twice and combine the results, e.g.:
-- Setup example data...
drop table if exists #Example;
create table #Example (
VendorId int,
Category varchar(10),
FirstSaleDate date,
StoreId int
);
insert #Example (VendorId, [Category], FirstSaleDate, StoreId)
values
(1, 'Car', '2021-01-01', 12),
(1, 'Clothes', '2021-01-02', 13),
(1, 'Toys', '2021-01-03', 14),
(1, 'Food', '2021-01-04', 15),
(1, 'Others', '2021-01-05', 15);
-- Pivot data...
with FirstSales as (
select VendorId, Category, FirstSaleDate from #Example
), Stores as (
select VendorId, 'StoreId_' + Category as Category, StoreId from #Example
)
select
FirstSales.VendorId,
Car, StoreId_Car,
Clothes, StoreId_Clothes,
Toys, StoreId_Toys,
Food, StoreId_Food,
Others, StoreId_Others
from (
select VendorId, Car, Clothes, Toys, Food, Others
from FirstSales
pivot (min(FirstSaleDate) for Category in ([Car], [Clothes], [Toys], [Food], [Others])) as pvt
) as FirstSales
join (
select VendorId, StoreId_Car, StoreId_Clothes, StoreId_Toys, StoreId_Food, StoreId_Others
from Stores
pivot (min(StoreId) for Category in ([StoreId_Car], [StoreId_Clothes], [StoreId_Toys], [StoreId_Food], [StoreId_Others])) as pvt
) as Stores on Stores.VendorId=FirstSales.VendorId;

SQL turn rows into columns

Hello is it possible to turn row values into columns.
I am using ORACLE SQL and I want to take the month and turn it into columns with the kpi value as shown below.
I tried partitions and merge statements but nothing seems to work.
I would really appreciate some help.
Thank you in advance.
Input data:
department
year
month
kpi
value
A
2000
1
sales
5000
A
2000
1
revenue per client
120
A
2000
2
sales
6000
A
2000
2
revenue per client
140
Desired Output:
department
year
kpi
1
2
A
2000
sales
5000
6000
A
2000
revenue per client
120
140
You can use pivot to do so:
Schema and insert statements:
create table mytable (department varchar(20),year int,month int,kpi varchar(50),value int);
insert into mytable values('A', 2000, 1, 'sales' ,5000);
insert into mytable values('A', 2000, 1, 'revenue per client', 120);
insert into mytable values('A', 2000, 2, 'sales' ,6000);
insert into mytable values('A', 2000, 2, 'revenue per client', 140);
Query:
select * from (
select department,year,month,kpi,value
from mytable
)
pivot
(
max(value)
for month in (1,2)
)
Output:
DEPARTMENT
YEAR
KPI
1
2
A
2000
revenue per client
120
140
A
2000
sales
5000
6000
db<fiddle here
You can use conditional aggrwegation:
select department, year, kpi,
max(case when month = 1 then value end) as month_1,
max(case when month = 2 then value end) as month_2
from t
group by department, year, kpi;

How to Sum two Different tax values amount individually

I've been trying to sum two different tax values amount from one table and my table is like below
Sales table:
Customer_id Tax_percent Tax_amount
100 5% 2.50
100 14.5% 6.75
101 5% 1.25
102 5% 2.00
101 14.5% 9.50
My output will be like:
total 5% amount is 5.75
total 14.5% amount is 16.25
Please help.
Use SUM and GROUP By functions :
SELECT Tax_percent , SUM(Tax_amount)
FROM your_table
GROUP BY Tax_percent
declare #Salestable table(Customer_id int, Tax_percent numeric(5,2), Tax_amount numeric(5,2))
insert into #Salestable values( 100 , 5 , 2.50)
insert into #Salestable values( 100 , 14.5 , 6.75)
insert into #Salestable values( 101 , 5 , 1.25)
insert into #Salestable values( 102 , 5 , 2.00)
insert into #Salestable values( 101 , 14.5 , 9.50)
select Tax_percent,sum(Tax_amount) from #Salestable group by Tax_percent