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

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

Related

Flag=1/0 based on multiple criteria on same column

I have a temp table that is being created, we will say that column 1 is YearMonth, column2 as user_id, Column 3 is Type.
YearMonth User_id Type
200101 1 x
200101 2 y
200101 2 z
200102 1 x
200103 2 x
200103 2 p
200103 2 q
I want to count userids based on flag based on type. Hence I am trying to set flag to 1 and 0 but it always results in 0.
So for e.g. when the type contains x or y or z AND type contains P or Q then flag=1 by YearMonth.
I am trying something like
SELECT count (distinct t1.user_id) as count,
t1.YearMonth,
case when t1.type in ('x','y','z')
and
t1.type in ('p','q') then 1 else 0 end as flag
FROM table t1
group by 2,3;
I would like to know why it doesn't give output as below:
count YearMonth Flag
0 200001 1
2 200001 0
1 200002 1
1 200002 0
What am I missing here? Thanks
If I follow you correctly, you can use two levels of aggregation:
select yearmonth, flag, count(*) cnt
from (
select yearmonth, id,
case when max(case when t1.type in ('x', 'y', 'z') then 1 else 0 end) = 1
and max(case when t1.type in ('p', 'q') then 1 else 0 end) = 1
then 1
else 0
end as flag
from mytable
group by yearmonth, id
) t
group by yearmonth, flag
This first flags users for each month, using conditional aggregation, then aggregates by flag and month.
If you also want to display 0 for flags that do not appear for a given month, then you can generate the combinations with a cross join first, then brin the above resultset with a left join:
select y.yearmonth, f.flag, count(t.id) cnt
from (select distinct yearmonth from mytable) y
cross join (values (0), (1)) f(flag)
left join (
select yearmonth, id,
case when max(case when t1.type in ('x', 'y', 'z') then 1 else 0 end) = 1
and max(case when t1.type in ('p', 'q') then 1 else 0 end) = 1
then 1
else 0
end as flag
from mytable
group by yearmonth, id
) t on t.yearmonth = y.yearmonth and t.flag = f.flag
group by y.yearmonth, f.flag
I thought a very similar idea as GMB, however, like him, I don't get the expected results. Likely, however, we both are assuming the expected results are wrong:
SELECT COUNT(DISTINCT UserID) AS [Count],
YearMonth,
CASE WHEN COUNT(CASE WHEN [Type] IN ('x','y','z') THEN 1 END) > 0
AND COUNT(CASE WHEN [Type] IN ('p','q') THEN 1 END) > 0 THEN 1 ELSE 0
END AS Flag
FROM (VALUES(200101,1,'x'),
(200101,2,'y'),
(200101,2,'z'),
(200102,1,'x'),
(200103,2,'x'),
(200103,2,'p'),
(200103,2,'q')) V(YearMonth,UserID,[Type])
GROUP BY YearMonth;

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;

Best way to do a Count in TSQL

I am not so good in TSQL and i want to write a report in this manner:
input: Table A
ID Company Product Flag
1 A Car Y
2 A Van N
3 B Van Y
4 A Part N
Output
Company Y N
A 1 2
B 1 0
if one can assist in TSQL...
You could use conditional aggregation:
SELECT Company
,SUM(CASE WHEN Flag = 'Y' THEN 1 ELSE 0 END) AS Y
,SUM(CASE WHEN Flag = 'N' THEN 1 ELSE 0 END) AS N
FROM tab
GROUP BY Company
You are looking for conditional aggregation:
select company,
sum(case when flag = 'Y' then 1 else 0 end) as num_y,
sum(case when flag = 'N' then 1 else 0 end) as num_n
from t
group by company;
You can use CASE expressions (the people call it "conditional aggregation") to count the flagged products per customer like this (which will ignore a record when the Product column is empty):
SELECT Company
, COUNT(CASE Flag WHEN 'Y' THEN Product END) AS Y
, COUNT(CASE Flag WHEN 'N' THEN Product END) AS N
FROM YourTable
GROUP BY Company;
Or you can use this PIVOT query, which is a short form of writing the above:
SELECT Company, Y, N
FROM (SELECT Company, Product, Flag FROM YourTable) AS src
PIVOT (COUNT(Product) FOR Flag IN (Y, N)) AS pvt;
use case when
select company,
sum(case when flag='Y' then 1 else 0 end) as Y,
sum(case when flag='N' then 1 else 0 end) as N from tabe_data
group by company

case statement for each row manipulations

Hi I have a table which has an ID and status.One ID can have multiple status but I have to pick status based on the conditions.
If ID 1 has Approved, Later,Modified I should Pick Approved and if the ID has only approved then Pick only Approved.But the case statement I got is not doing per ID.It is changing the overall data based on status.Please advise
select ID,
CASE
WHEN status = 'Approved'
AND status IN(
'Modified',
'Later'
) THEN 'Partial Modified'
WHEN status = 'Approved' THEN 'Approved'
when status IN('Modified','Edited') THEN 'Modified'
else status
END status group by ID,Status
This can be done with an ordering condition in row_number.
select top 1 with ties *
from tbl
order by row_number() over(partition by id order by case when status='Approved' then 1
when status='Modified' then 2
else 3 end)
I think you want an aggregation, so something like this:
(CASE WHEN SUM(CASE WHEN status = 'Approved' THEN 1 ELSE 0 END) > 0
THEN 'Approved'
WHEN SUM(CASE WHEN status = 'Modified' THEN 1 ELSE 0 END) > 0
THEN 'Modified'
ELSE MAX(status)
END)
Of course, you can also do this using window functions:
(CASE WHEN SUM(CASE WHEN status = 'Approved' THEN 1 ELSE 0 END) OVER (PARTITION BY id) > 0
THEN 'Approved'
WHEN SUM(CASE WHEN status = 'Modified' THEN 1 ELSE 0 END) OVER (PARTITION BY id) > 0
THEN 'Modified'
ELSE MAX(status) OVER (PARTITION BY id)
END)

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

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)