Transfer table from vertical to horizontal in sql - sql

I want to transfer table from
to what looks like this:
Not sure how to approach?
Code I had is this
FROM TABLE A,
(SELECT PART_NO, SUM(QUANTITY) AS Type_1
FROM TABLE
WHERE STYPE = 'Type_1'
GROUP BY PART_NO, STYPE) B,
(SELECT PART_NO, SUM(QUANTITY) AS Type_2
FROM TABLE
WHERE STYPE = 'Type_2'
GROUP BY PART_NO, STYPE) C,
(SELECT PART_NO, SUM(QUANTITY) AS Type_3
FROM TABLE
WHERE STYPE = 'Type_3'
GROUP BY PART_NO, STYPE) D,
(SELECT PART_NO, SUM(QUANTITY) AS Type_4
FROM TABLE
WHERE STYPE = 'Type_4'
GROUP BY PART_NO, STYPE) E
WHERE A.PART_NO = B.PART_NO
AND A.PART_NO = C.PART_NO
AND A.PART_NO = D.PART_NO
AND A.PART_NO = E.PART_NO
AND A.PART_NO = F.PART_NO
GROUP BY A.PART_NO, B.Type_1, C.Type_2, D.Type_2, E.Type_4
But it removes the rows with nan. Not sure where did i do wrong.

This is a type of pivoting that you can produce using conditional aggregation.
For example, you can do:
select
part_no,
sum(case when stype = 'Type 1' then quantity end) as type_1,
sum(case when stype = 'Type 2' then quantity end) as type_2,
sum(case when stype = 'Type 3' then quantity end) as type_3
from my_table
group by part_no

Related

Sum of rows as columns

I have a table as below with (ID, DATE, Category, Price) as columns
I would like the output as below.
Could you please help me?
Thank you
You can go for conditional grouping as given below. you can go for IN clause to make code simpler.
SELECT ID, DATE,
SUM(CASE WHEN Category IN ('R','F') THEN Price ELSE 0 END) AS Regular,
SUM(CASE WHEN Category IN ('B','C') THEN Price ELSE 0 END) AS Bonus,
SUM(CASE WHEN Category IN ('K','W','O','OW') THEN Price ELSE 0 END) AS Other
FROM TableName
GROUP BY ID, DATE
Per my understanding, you want to do group by Date column and show the SUM of the values in new column
Try this (haven't test it):
select ID, Date,
sum((case when Category = 'R' then Price) + (case when Category = 'F' then Price)) as 'Regular (R+F)',
sum((case when Category = 'B' then Price) + (case when Category = 'C' then Price)) as 'Bonus (B+C)',
sum((case when Category = 'K' then Price) + (case when Category = 'W' then Price)
+ (case when Category = 'O' then Price) + (case when Category = 'OW' then Price)) as 'Other (K+W+O+OW)'
from t
group by Date;

expected result is not getting

I have a data like this:
And I want this - I am trying with PIVOT but not getting the expected results:
Query is
SELECT AttendeeID,[Quantity1],[PROD1],[Quantity2],[PROD2],[Quantity3],[PROD3] FROM
(SELECT * ,
row_number() over(partition by AttendeeID order by AttendeeID)rn
from #ProductTestingwithPosition2) TT
PIVOT
(MAX(product) for ProductPosition in ([PROD1],[PROD2],[PROD3])) AS Tab2
PIVOT
(sum(Quantity) for QuantityPosition in ([Quantity1],[Quantity2],[Quantity3])) AS Tab3
I am getting this output:
Just use conditional aggregation:
SELECT AttendeeID,
MAX(CASE WHEN ProductPosition = 'PROD1' THEN product END) as prod1,
MAX(CASE WHEN QuantityPosition = 'QUANTITY1' THEN quantity END) as quantity1,
MAX(CASE WHEN ProductPosition = 'PROD2' THEN product END) as prod2,
MAX(CASE WHEN QuantityPosition = 'QUANTITY2' THEN quantity END) as quantity2,
MAX(CASE WHEN ProductPosition = 'PROD3' THEN product END) as prod3,
MAX(CASE WHEN QuantityPosition = 'QUANTITY3' THEN quantity END) as quantity3
FROM (SELECT ptp.* ,
row_number() over (partition by AttendeeID, ProductPosition order by AttendeeID) as seqnum
FROM #ProductTestingwithPosition2 ptp
) ptp
GROUP BY AttendeeID, seqnum;
PIVOT -- in addition to being non-standard -- is very finicky. Conditional aggregation is much more powerful and less prone to errors.

Combine Table in SQL

I have two tables would like to combine.
I would like the table will automatically add a row for image2 when there are new generalname in image1.
select B.Trsdate, count(B.Billno) As Billno, sum(B.pax) As Pax, sum(B.Grossamount) As GrossAmount, sum(B.discountamount) As Discount, sum(B.taxamount) As Tax, sum(B.servicechargeamount) As SCharge, sum(B.nettamount) As NettAmt, sum(B.rounddiff) As RDiff, sum(B.roundamt) As RoundAmt, sum(B.reversalYN) As RevBillNo, SUM(GD.CASH) AS 'P_CASH', SUM(GD.VISA) AS 'P_VISA', SUM(GD.MASTER) AS 'P_MASTER', SUM(GD.AMEX) AS 'P_Amex', SUM(GD.CityLedger) AS 'P_CityLedger', SUM(GD.OtherPayment) As 'P_Other'
from vpos_eod_bills As B
INNER JOIN
(
SELECT TrsNo,SUM(CASH) as CASH,SUM(Visa) as Visa, SUM(Master) as Master, SUM(Amex) AS Amex, SUM(CityLedger) as CityLedger, SUM(OtherPayment) as OtherPayment, SUM(Total) as Total FROM
(
select TrsNo, GENERALNAME,
(case WHEN(Generalname IN ('CASH'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'CASH',
(case WHEN(Generalname IN ('VISA'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'Visa',
(case WHEN(Generalname IN ('MASTER'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'Master',
(case WHEN(Generalname IN ('AMEX'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'Amex',
(case WHEN(Generalname = 'City Ledger' OR Generalname = 'CREDIT A/C' OR Generalname = 'BOSS' OR Generalname = 'ENTERTAINMENT')
THEN
SUM(AMOUNT)
ELSE
0
END) as 'CityLedger',
(case WHEN(Generalname not IN ('CASH','Voucher','VISA','MASTER','AMEX','JCB','City Ledger','CREDIT A/C','BOSS','ENTERTAINMENT') and (Generalname not like '%card%') and (Generalname not like '%Coupon%') and (Generalname not like '%GROUPON%') and (Generalname not like '%COURSE%'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'OtherPayment',
SUM(AMOUNT) as Total
from Vpos_eod_GeneralDetails
where BillType = 'P'
group by TrsNo, GeneralName
) As A
Group By A.trsno
)As GD ON GD.TrsNo = B.TrsNo
where B.PaidStatus = '1' and B.VoidStatus = '0' and (B.trsdate between '20200101' and '20200131')
group by B.trsdate

SQL - Trying to find customer by their shopping channel

Hello I am trying to find the customers who just shop online and just shop in store and the customers who shop both online and in store. So when I add them up they should be equal to my total customers.
I am trying to find the new and returning customer by their shopping channel. I need a sql to give me all the new customer and returning customers who have shopped in store, and then in a separate table all the new/returning customers who have shopped only online and then people who have shopped both online and in store (crossover customers). So that when I add off them together they should be equal to my total customers in each category (new and returning).
It should look like below:
how data should look like
I have created a sample database as well. I am also trying to break the customer by new and returning customers and later by their age range.
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=96a7b85c8ca0da7f7c40f20205964d9b
these are some of the queries which I have tried: Below is the one which shows me the new and the returning customers who have only bough online:
SELECT
DECODE(is_new, 1, 'New Customers', 'Returning Customers') type_of_customer,
COUNT(distinct individual_id) count_of_customers,
SUM(count_of_transactions) count_of_transactions,
SUM(sum_of_quantity) sum_of_quantity
FROM (
SELECT
individual_id,
SUM(dollar_value_us),
sum(quantity) sum_of_quantity,
count(distinct transaction_number) count_of_transactions,
CASE WHEN MIN(txn_date) = min_txn_date THEN 1 ELSE 0 END is_new
FROM (
SELECT
a.individual_id,
a.dollar_value_us,
a.txn_date,
a.quantity,
a.transaction_number,
b.gender,
b.age,
MIN(a.txn_date) OVER(PARTITION BY a.individual_id) min_txn_date,
A.TRANTYPE
FROM transaction_detail_mv a
join gender_details b on a.individual_id = b.individual_id
WHERE
a.brand_org_code = 'BRAND'
AND a.is_merch = 1
AND a.currency_code = 'USD'
AND a.line_item_amt_type_cd = 'S'
AND a.individual_id not in (select individual_id from transaction_detail_mv where trantype = 'POS' )
)
WHERE
txn_date >= TO_DATE('10-02-2019', 'DD-MM-YYYY')
AND txn_date < TO_DATE('17-02-2019', 'DD-MM-YYYY')
GROUP BY
individual_id,
min_txn_date
)
GROUP BY is_new
and to find the new and returnign customers who buy form POS is bewow:
SELECT
DECODE(is_new, 1, 'New Customers', 'Returning Customers') type_of_customer,
COUNT(distinct individual_id) count_of_customers,
SUM(count_of_transactions) count_of_transactions,
SUM(sum_of_quantity) sum_of_quantity
FROM (
SELECT
individual_id,
SUM(dollar_value_us),
sum(quantity) sum_of_quantity,
count(distinct transaction_number) count_of_transactions,
CASE WHEN MIN(txn_date) = min_txn_date THEN 1 ELSE 0 END is_new
FROM (
SELECT
a.individual_id,
a.dollar_value_us,
a.txn_date,
a.quantity,
a.transaction_number,
b.gender,
b.age,
MIN(a.txn_date) OVER(PARTITION BY a.individual_id) min_txn_date,
A.TRANTYPE
FROM transaction_detail_mv a
join gender_details b on a.individual_id = b.individual_id
WHERE
a.brand_org_code = 'BRAND'
AND a.is_merch = 1
AND a.currency_code = 'USD'
AND a.line_item_amt_type_cd = 'S'
AND a.individual_id not in (select individual_id from transaction_detail_mv where trantype = 'ONLINE' )
)
WHERE
txn_date >= TO_DATE('10-02-2019', 'DD-MM-YYYY')
AND txn_date < TO_DATE('17-02-2019', 'DD-MM-YYYY')
GROUP BY
individual_id,
min_txn_date
)
GROUP BY is_new
I am trying to find new and old customers who have shopped both online and in POS. Please HELP !
You are almost there. Try this:
SELECT
DECODE(is_new, 1, 'New Customers', 'Returning Customers') type_of_customer,
COUNT(distinct individual_id) count_of_customers,
SUM(count_of_transactions) count_of_transactions,
SUM(sum_of_quantity) sum_of_quantity
FROM (
SELECT
individual_id,
SUM(dollar_value_us),
sum(quantity) sum_of_quantity,
count(distinct transaction_number) count_of_transactions,
CASE WHEN MIN(txn_date) = min_txn_date THEN 1 ELSE 0 END is_new
FROM (
SELECT
a.individual_id,
a.dollar_value_us,
a.txn_date,
a.quantity,
a.transaction_number,
b.gender,
b.age,
MIN(a.txn_date) OVER(PARTITION BY a.individual_id) min_txn_date,
A.TRANTYPE
FROM transaction_detail_mv a
join gender_details b on a.individual_id = b.individual_id
WHERE
a.brand_org_code = 'BRAND'
AND a.is_merch = 1
AND a.currency_code = 'USD'
AND a.line_item_amt_type_cd = 'S'
AND a.individual_id not in (select individual_id from transaction_detail_mv where ((trantype = 'ONLINE') OR (trantype = 'POS') )
)
WHERE
txn_date >= TO_DATE('10-02-2019', 'DD-MM-YYYY')
AND txn_date < TO_DATE('17-02-2019', 'DD-MM-YYYY')
GROUP BY
individual_id,
min_txn_date
)
GROUP BY is_new

column headers in select Union query

I have to select query like the following example :
Select name,
SUM(DECODE(TO_CHAR(Datee,'MM'),'01',PRICE)) JAN_12,
SUM(DECODE(TO_CHAR(Datee,'MM'),'02',PRICE)) FEB_12
from price_list_LastYear
UNION ALL
Select name,
SUM(DECODE(TO_CHAR(Datee,'MM'),'01',PRICE)) JAN_11,
SUM(DECODE(TO_CHAR(Datee,'MM'),'02',PRICE)) FEB_11
from price_list_TwoLastYear.
When I execute the query, In my column header I get name, JAN_12, FEB_12.
I want to combine my results like : name, JAN_11, JAN_12, FEB_11,FEB_12.
Try this:
SELECT P1.name,
SUM(DECODE(TO_CHAR(P1.Datee,'MM'),'01',P1.PRICE)) JAN_12,
SUM(DECODE(TO_CHAR(P1.Datee,'MM'),'02',P1.PRICE)) FEB_12,
SUM(DECODE(TO_CHAR(P2.Datee,'MM'),'01',P2.PRICE)) JAN_11,
SUM(DECODE(TO_CHAR(P2.Datee,'MM'),'02',P2.PRICE)) FEB_11
FROM price_list_LastYear P1
JOIN price_list_TwoLastYear P2
ON P1.nmae = P2.nmae
GROUP BY P1.nmae
If same name doesn't exists in both tables try this:
SELECT N.name,
SUM(DECODE(TO_CHAR(P1.Datee,'MM'),'01',P1.PRICE)) JAN_12,
SUM(DECODE(TO_CHAR(P1.Datee,'MM'),'02',P1.PRICE)) FEB_12,
SUM(DECODE(TO_CHAR(P2.Datee,'MM'),'01',P2.PRICE)) JAN_11,
SUM(DECODE(TO_CHAR(P2.Datee,'MM'),'02',P2.PRICE)) FEB_11
FROM
(
SELECT name FROM price_list_LastYear
UNION
SELECT name FROM price_list_TwoLastYear
) N
LEFT JOIN price_list_LastYear P1
ON N.nmae = P1.name
LEFT JOIN price_list_TwoLastYear P2
ON N.nmae = P2.name
GROUP BY N.name
Try this
SELECT A.*, B,JAN_11, B.FEB_11 FROM (
Select name,
SUM(DECODE(TO_CHAR(Datee,'MM'),'01',PRICE)) JAN_12,
SUM(DECODE(TO_CHAR(Datee,'MM'),'02',PRICE)) FEB_12
from price_list_LastYear
Group By Name) A
LEFT OUTER JOIN (
Select name,
SUM(DECODE(TO_CHAR(Datee,'MM'),'01',PRICE)) JAN_11,
SUM(DECODE(TO_CHAR(Datee,'MM'),'02',PRICE)) FEB_11
from price_list_TwoLastYear
Group By Name) B ON A.name = B.Name
Or
Select name,
SUM(CASE WHEN Yr = '11' THEN DECODE(Mnth,'01',PRICE) ELSE NULL END) JAN_11,
SUM(CASE WHEN Yr = '12' THEN DECODE(Mnth,'01',PRICE) ELSE NULL END) JAN_12,
SUM(CASE WHEN Yr = '11' THEN DECODE(Mnth,'02',PRICE) ELSE NULL END) FEB_11,
SUM(CASE WHEN Yr = '12' THEN DECODE(Mnth,'02',PRICE) ELSE NULL END) FEB_12
from
(
SELECT '12' As yr, name, TO_CHAR(Datee,'MM') Mnth, Price
FROM price_list_LastYear
UNION ALL
SELECT '11' As yr, name, TO_CHAR(Datee,'MM') Mnth, Price
FROM price_list_TwoLastYear
)
GROUP BY Name
If the name does not exist in both tables, then it might be difficult to use a JOIN. So here is a version using UNION ALL and then applying an aggregate function with a CASE expression to transform the data to columns:
SELECT name,
sum(case when Month = 'JAN_12' then price else 0 end) JAN_12,
sum(case when Month = 'FEB_12' then price else 0 end) FEB_12,
sum(case when Month = 'JAN_11' then price else 0 end) JAN_11,
sum(case when Month = 'FEB_11' then price else 0 end) FEB_11
FROM
(
Select name,
PRICE,
case
when TO_CHAR(Datee,'MM') = '01' Then 'JAN_12'
when TO_CHAR(Datee,'MM') = '02' Then 'FEB_12' End Month
from price_list_LastYear
WHERE TO_CHAR(Datee,'MM') in ('01', '02')
UNION ALL
Select name,
PRICE,
case
when TO_CHAR(Datee,'MM') = '01' Then 'JAN_11'
when TO_CHAR(Datee,'MM') = '02' Then 'FEB_11' End Month
from price_list_TwoLastYear
WHERE TO_CHAR(Datee,'MM') in ('01', '02')
) src
GROUP BY name