how to Sum "case when" clause after inner join without duplication - sql

I am a new member of Stackoverflow (and also I'm a new of coding sql) if i do any mistakes about my question please advise me :)
I'm trying to get SUM of Amount in CASE WHEN Clause.
Here is my table
tableA
UserID transid Brand Amount
UserA 109974 MIX 960.00 --BrandMIX=A & B
UserB 109975 B 894.00
UserC 109976 C 350.00
UserC 109977 MIX 300.00 --BrandMIX=C & D
tableB
Row transid Brand
1 109974 A
2 109974 B
3 109975 B
4 109976 C
5 109977 C
6 109977 D
I tried inner join table a and table b on a.soid = b.soid
and when i SUM it, result was wrong due to duplication of transid in table b.
here is my coding.
SELECT UserID
,CASE WHEN COUNT(DISTINCT(b.transid )) <> 0 THEN COUNT(DISTINCT(b.transid ))
ELSE NULL END) AS 'Frequency'
,SUM(Amount) as 'TotalAmount'
,YEAR(transdatetime) AS 'Year'
,SUM (CASE [Brand] WHEN 'AA' THEN 1 ELSE 0 END) AS [BrandA]
,SUM (CASE [Brand] WHEN 'BB' THEN 1 ELSE 0 END) AS [BrandB]
,SUM (CASE [Brand] WHEN 'CC' THEN 1 ELSE 0 END) AS [BrandC]
,SUM (CASE [Brand] WHEN 'DD' THEN 1 ELSE 0 END) AS [BrandD]
,SUM (CASE [Brand] WHEN 'ZZ' THEN 1 ELSE 0 END) AS [BrandZ]
FROM tableA a
INNER tableB b ON a.transid = b.transid
WHERE is_paid = 'N'
GROUP BY UserID, YEAR(transdatetime)
Result that I got
Result that I want
I added ROW_NUMBER() into tableB, I want to SUM(Amount) WHERE MIN(ROW_NUMBER), is it impossible?
Please advise, thank you.

Based on your row_number i.e (row column of tableB) I have modified your query to take min(row) values. Please try this...If this does not work please post the complete tables structures.
SELECT UserID
,CASE WHEN COUNT(DISTINCT(b.transid )) <> 0 THEN COUNT(DISTINCT(b.transid ))
ELSE NULL END AS 'Frequency'
,SUM(Amount) as 'TotalAmount'
,YEAR(transdatetime) AS 'Year'
,SUM (CASE [Brand] WHEN 'AA' THEN 1 ELSE 0 END) AS [BrandA]
,SUM (CASE [Brand] WHEN 'BB' THEN 1 ELSE 0 END) AS [BrandB]
,SUM (CASE [Brand] WHEN 'CC' THEN 1 ELSE 0 END) AS [BrandC]
,SUM (CASE [Brand] WHEN 'DD' THEN 1 ELSE 0 END) AS [BrandD]
,SUM (CASE [Brand] WHEN 'ZZ' THEN 1 ELSE 0 END) AS [BrandZ]
FROM tableA a
INNER JOIN tableB b ON a.transid = b.transid
WHERE is_paid = 'N' AND b.row in (select min(row) from tableB group by transid)
GROUP BY UserID, YEAR(transdatetime)

Related

SQL aggregate multiple values in a column then Pivot

I've got a table with a particular column of products. Let's say product A, B, and C.
This table also has a date column.
I'd like to built a pivot table by month, with columns being combinations of users of these products.
So
Just A
Just B
Just C
A and B
A and C
B and C
A, B and C.
I can do it without the combination values as follows:
Select * from
(Select product_type, date_month, person_id
From products_table)
PIVOT (
Count(person_id)
For product_type in
(
[A]
,[B]
,[C]
)
) As pivot_table;
So my question is, how do I build combinations of these values and then add them to the pivot? Do I need to build the combination columns first and then add them to the pivot somehow?
DATE_MONTH | A | B | C | A_B | A_C | B_C | A_B_C
01-01-2020 | 30 | 75 | 10 | 105 | 40 | 85| 115
I think you're looking for something like this. First it determines the distinct product types for each person_id. Then it aggregates the product types using STRING_AGG to create the groupings. Then it uses conditional aggregation to count the person_id's in each category by month.
Using STRING_AGG SQL Server 2017+
with
dist_prod_typ_cte(person_id, product_type) as (
select distinct person_id, product_type
from products_table),
prod_grp_cte(person_id, prod_grp) as (
select person_id, string_agg(product_type, '_') within group (order by product_type) p_type_grp
from dist_prod_typ_cte
group by person_id)
select pt.date_month,
count(case when pgc.prod_grp='A' then pt.person_id else null end) A,
count(case when pgc.prod_grp='B' then pt.person_id else null end) B,
count(case when pgc.prod_grp='C' then pt.person_id else null end) C,
count(case when pgc.prod_grp='A_B' then pt.person_id else null end) A_B,
count(case when pgc.prod_grp='A_C' then pt.person_id else null end) A_C,
count(case when pgc.prod_grp='B_C' then pt.person_id else null end) B_C,
count(case when pgc.prod_grp='A_B_C' then pt.person_id else null end) A_B_C
from products_table pt
join prod_grp_cte pgc on pt.person_id=pgc.person_id
group by pt.date_month;
Using STUFF' and 'FOR XML SQL Server 2016 and prior
with
dist_prod_typ_cte(person_id, product_type) as (
select distinct person_id, product_type
from products_table),
prod_grp_cte(person_id, prod_grp) as (
select person_id, stuff((select '_' + cast(dptc_in.product_type as varchar(18))
from dist_prod_typ_cte dptc_in
where dptc.person_id = dptc_in.person_id
order by dptc_in.product_type
for xml path('')), 1, 1, '')
from dist_prod_typ_cte
group by person_id)
select pt.date_month,
count(case when pgc.prod_grp='A' then pt.person_id else null end) A,
count(case when pgc.prod_grp='B' then pt.person_id else null end) B,
count(case when pgc.prod_grp='C' then pt.person_id else null end) C,
count(case when pgc.prod_grp='A_B' then pt.person_id else null end) A_B,
count(case when pgc.prod_grp='A_C' then pt.person_id else null end) A_C,
count(case when pgc.prod_grp='B_C' then pt.person_id else null end) B_C,
count(case when pgc.prod_grp='A_B_C' then pt.person_id else null end) A_B_C
from products_table pt
join prod_grp_cte pgc on pt.person_id=pgc.person_id
group by pt.date_month;

Comparing values in two columns and returning values on conditional bases using sql hive

I have two columns, I want to get an output based on a comparative basis of both. My data is somewhat like:
Customer Id status
100 A
100 B
101 B
102 A
103 A
103 B
So a customer can have a status A or B or both, I have to segrerate them on customer id basis for a status. If status A and B then return happy, if only A, return Avg and if only B return Sad.
try the below query,
SELECT DISTINCT Customer_Id,
(CASE WHEN COUNT(*) OVER(PARTITION BY Customer_Id) > 1 THEN 'happy'
WHEN Tstatus = 'A' THEN 'Avg'
ELSE 'Sad'END) AS New_Status
FROM #table1
GROUP BY Customer_Id,Tstatus
if Customer Id and status is a unique combination then
STEP 1: use case to determine a or b
SELECT customer id
,CASE WHEN avg(case when [status] ='A' then 0 else 2 end)
FROM [Your Table]
group by[customer id]
and step 2 will be casing avg into result: like this
SELECT customer id
,CASE WHEN (avg(case when [status] ='A' then 0 else 2 end)) = 1 THEN 'happy' ELSE WHEN (avg(case when [status] ='A' then 0 else 2 end)) = 0 THEN 'Avg' ELSE 'Sad' END
FROM [Your Table]
group by[customer id]
I would do this simply as:
select customer_id,
(case when min(status) <> max(status) then 'happy'
when min(status) = 'A' then 'avg'
else 'sad'
end)
from t
where status in ('A', 'B')
group by customer_id

(store procedure) combine result 2 rows into 1 row result

can i combine result row 3 and row 4 into 1 row record?
select #fYear as [Year],
(case when main.Description in ('Kecil', 'Tanah') then 'JK'
else main.Description
end) as description,
--CardType,
sum(case when MONTH(blue.AppliedDate) = 1 then 1 else 0 end) as Jan_Collection,
sum(case when MONTH(blue.AppliedDate) = 2 then 1 else 0 end) as Feb_Collection,
...
from tblR as main
left join tblP as b on main.requestorid = b.requestorid
left join tblB as blue on b.partyid = blue.partyid and YEAR(blue.AppliedDate) = #fYear
group by (case when main.Description in ('Kecil', 'Tanah') then 'JK'
else main.Description
end)
this output like:
https://gyazo.com/d930cb2aee92f90ba31dd543d6ca64f3
but can i display combine record row 3 and 4 into 1 record like JK like this picture: https://gyazo.com/a89ed2fa04b51135bf8601d59d4af0b2
Thanks.
If you want to combine those specific descriptions, you can use a case, both in the select and the group by:
select #fYear as [Year],
(case when description in ('kecil', 'Tanah') then 'JK'
else main.Description
end) as Description,
sum(case when MONTH(blue.AppliedDate) = 1 then 1 else 0 end) as Jan_Collection,
sum(case when MONTH(blue.AppliedDate) = 2 then 1 else 0 end) as Feb_Collection,
...
from tblR main left join
tblP b
on main.requestorid = b.requestorid left join
tblB
blue
on b.partyid = blue.partyid and YEAR(blue.AppliedDate) = #fYear
group by (case when description in ('kecil', 'Tanah') then 'JK'
else main.Description
end)

Combining rows with NULL columns

select
COUNT(Table1.ID) as count_shipped,
null as count_shipped
from Table1
where
table1.saleStatus='shipped'
and table1.saleApproved='yes'
union
select
null,
COUNT(Table1.ID) as count_pending
from Table1
where
table1.saleStatus in ('Pending', 'awaiting payment', 'backorder')
This gives this output
count_shipped count_shipped
NULL 5
4 NULL
but I don't want Null I only want 4 5 in one line Can anybody help me how to do this sql server?
You can use a case to sum up your conditions
select sum(case when saleStatus = 'shipped' and table1.saleApproved = 'yes'
then 1
else 0
end) as count_shipped,
sum(case when saleStatus in ('Pending', 'awaiting payment', 'backorder')
then 1
else 0
end) as count_pending
from Table1

Full Join on two queries

I'm trying to do a full join on two SQL queries, below:
1st Query:
SELECT
ID
,SUM(CASE WHEN reason = 4 THEN 0 ELSE quantity*price END) AS TValue
,COUNT(*) AS CountAll
FROM table1
WHERE Date>=#StartDate AND Date<=#EndDate
GROUP BY ID
2nd Query:
SELECT
ID
,SUM(CASE WHEN reason = 1 THEN 1 ELSE 0 END) AS New
,SUM(CASE WHEN reason = 6 THEN 1 ELSE 0 END) AS Amend
,SUM(CASE WHEN reason = 5 THEN 1 ELSE 0 END) AS Cancel
FROM Table2
WHERE Date2 >=#StartDate AND Date2<= #EndDate
GROUP BY ID
Result from query1
ID CountAll TValue
-------------------------
id1 24 1020
id2 13 2030
id3 4 120
Result from query 2:
ID New Amend Cancel
--------------------------------
id1 12 4 6
id2 7 6 1
id4 2 1 2
Needed output:
ID TValue CountAll New Amend Cancel Total(countall+new+amend+cancel)
----------------------------------------------------------------------------------------
Id1 1020 24 12 4 6 46
Id2 2030 13 7 6 1 27
id3 120 4 0 0 0 4
Id4 0 0 2 1 2 5
I'll post my current solution if requested, but it is pretty far from working.
I've been doing a bit of research and I think I need to either make a union to join the ID'S, or just do a Full Join. (Second day ever doing sql)
Try this,
SELECT *
FROM
(
SELECT ID ,
SUM(CASE WHEN reason = 4 THEN 0 ELSE quantity*price END) AS TValue,
COUNT(*) AS CountAll
FROM table1
WHERE Date>=#StartDate AND Date<=#EndDate
GROUP BY ID
) a FULL JOIN
(
SELECT ID ,
SUM(CASE WHEN reason = 1 THEN 1 ELSE 0 END) AS New ,
SUM(CASE WHEN reason = 6 THEN 1 ELSE 0 END) AS Amend ,
SUM(CASE WHEN reason = 5 THEN 1 ELSE 0 END) AS Cancel
FROM Table2
WHERE Date2 >=#StartDate AND Date2<= #EndDate
GROUP BY ID
) b ON a.ID = b.ID
I would write something like below:
select decode (a.id, null, b.id, a.id) as ID, a.TValue, CountAll, b.new, b.Amend, b.cancel
from (SELECT ID ,SUM(CASE WHEN reason = 4 THEN 0 ELSE quantity*price END)
AS TValue ,COUNT(*) AS CountAll
FROM table1
WHERE Date>=#StartDate AND Date<=#EndDate GROUP BY ID
) a FULL OUTER JOIN
(SELECT ID , SUM(CASE WHEN reason = 1 THEN 1 ELSE 0 END)
AS New ,SUM(CASE WHEN reason = 6
THEN 1 ELSE 0 END) AS Amend ,
SUM(CASE WHEN reason = 5 THEN 1 ELSE 0 END) AS Cancel
FROM Table2 WHERE Date2 >=#StartDate AND Date2<= #EndDate GROUP BY ID
) b
on a.id = b.id
have you tried this...
select isnull (a.id,b.id) as ID, a.TValue, CountAll, b.new, b.Amend, b.cancel
from (SELECT ID ,SUM(CASE WHEN reason = 4 THEN 0 ELSE quantity*price END) AS TValue ,COUNT(*) AS CountAll
FROM table1
WHERE Date>=#StartDate AND Date<=#EndDate GROUP BY ID ) a
FULL OUTER JOIN (SELECT ID , SUM(CASE WHEN reason = 1 THEN 1 ELSE 0 END) AS New ,SUM(CASE WHEN reason = 6 THEN 1 ELSE 0 END) AS Amend , SUM(CASE WHEN reason = 5 THEN 1 ELSE 0 END) AS Cancel
FROM Table2 WHERE Date2 >=#StartDate AND Date2<= #EndDate GROUP BY ID ) b on a.id = b.id