Group by to include case statement inside SQL statement - sql

I have a table which stores purchase info from sellers and table contains rating to every purchase out of 5 stars. I want to have output Group By sellers and Each sellers good(Above 3) and bad(Below 4) ratings count
PurchaseId SellerId PurchaseRating
1 ABC 2
2 ABC 5
3 DEF 1
4 XYZ 2
5 DEF 4
7 ABC 3
OUTPUT
SellerId TotalOrders AvgRating Above3*(4&5) Below4*(1 to 3)
ABC 3 3.3 1 2
DEF 2 2.5 1 1
XYZ 1 2 0 1
For first 3 columns I am getting result using this
Select SellerId, Count(P.Id) TotalOrders, Avg(PurchaseRating) AvgRating,
CASE WHEN P.PurchaseRating >= 4 THEN 1 ELSE 0 END AS Above3*(4&5)
from
[dbo].[AmazonAbeOrdersPurchaseInfo] P
Where PurchaseRating is not null
Group by P.SellerId
order by TotalOrders desc
Unable to identify how to include case in group by clause.

You are trying to do conditional aggreation. The important thing is that you want the conditional expression inside the aggregate function:
select
sellerId,
count(*) totalOrders,
avg(purchaseRating) avgRating,
sum(case when purchaseRating > 3 then 1 else 0 end) above3,
sum(case when purchaseRating < 4 then 1 else 0 end) below4
from [dbo].[AmazonAbeOrdersPurchaseInfo]
where purchaseRating is not null
group by sellerId
order by totalOrders desc

Related

how to sum with case with oracle sql

I m having data in columns as:
item_id
month_in
amount
1
1
1500
1
1
1000
2
1
2500
3
1
2600
3
1
1000
4
1
2700
4
1
1000
1
2
1500
1
2
2000
2
2
1000
3
3
2500
3
3
2500
4
3
1000
4
3
2500
I want to have like this result
item_id
januari
februari
maret
1
2500
3500
0
2
2500
1000
0
3
3600
0
0
4
3700
0
3500
in oracle sql query how to solve this.
please help me
I have try this
select
item_id,
(case month_in=1 then sum(amout) end) AS januari
from table
group by item_id, month_in
order by item_id asc
but not working as I expected
We can try a pivot query here:
SELECT
item_id,
SUM(CASE WHEN month_in = 1 THEN amount ELSE 0 END) AS januari,
SUM(CASE WHEN month_in = 2 THEN amount ELSE 0 END) AS februari,
SUM(CASE WHEN month_in = 3 THEN amount ELSE 0 END) AS maret
FROM yourTable
GROUP BY
item_id
ORDER BY
item_id;
You almost got it. This is the simplest solution, without extra hassle:
SELECT
item_id,
SUM(CASE WHEN month_in = 1 THEN amount ELSE 0 END) AS januari,
SUM(CASE WHEN month_in = 2 THEN amount ELSE 0 END) AS februari,
SUM(CASE WHEN month_in = 3 THEN amount ELSE 0 END) AS maret
from table
group by item_id
order by item_id asc
You don't need to define the months as a separate rowset, because the months are defined as values 1, 2, 3, ... as columns. Similarly, the items are defined by the group by function.

Create Aggregate Table from binary columns on SQL

Table1
customerid
jan21
feb21
mar21
apr21
123
1
0
0
1
124
0
1
0
1
125
0
0
1
1
126
1
1
0
1
i have a table as above and I would like to create another table like this:
Table2
month
jan21
feb21
mar21
apr21
jan21
2
0
0
2
feb21
-
2
0
2
mar21
-
-
1
2
apr21
-
-
-
4
Basically, I would like to count how many customers are active in each month on condition that they are active in the given month.
I left empty for the left side of the table since it will be the symmetrical of the right side but if someone may come with a solution filled both sides of the table, it is still more than welcome.
I do it with lots of subqueries and WHERE conditions and I sum each month by changing the where condition for each month every time. However, it is very time consuming and I wonder if there is a one time SQL query to do this task.
By the way, I am working on POSTGRESQL.
Here is my query. I also create table1 within the query as well.
I change the jan21 = 1 for each month
select
sum(jan21) as jan21,
sum(feb21) as feb21,
sum(mar21) as mar21,
sum(apr21) as apr21
from(
select customerid,
sum(jan21) as jan21,
sum(feb21) as feb21,
sum(mar21) as mar21,
sum(apr21) as apr21
from (
with orders as (
select customerid, to_char(orderdate, 'YYYYMM') as orderdate
from ordertable
group by customerid, orderdate
)
select distinct customerid,
case
when orderdate = '202101' then 1 else 0 end as jan21,
case
when orderdate = '202102' then 1 else 0 end as feb21,
case
when orderdate = '202103' then 1 else 0 end as mar21,
case
when orderdate = '202104' then 1 else 0 end as apr21
from orders
) t1 group by customerid
) t25
where jan21 = 1

Sqlite group by distinct count

I have table of customers operations:
date, client_id, gender
1 1 M
1 1 M
1 2 M
1 2 M
1 3 F
2 1 M
2 1 M
2 1 M
2 2 M
2 2 M
2 3 F
2 3 F
2 4 F
2 5 M
2 5 M
etc
Desired output is:
date, amount of males, (also need amount of females)
1 2 1
2 3 2
I need to group it by date, so i did it, then my goal is to find amount of each gender in each grouped group.
so i tried to do this to count amount of males:
sum(case when gender = 'M' then 1 else NULL end) as 'M%'
but its counted clients id 1 and 2 two times each, but i need to count it distinct.
On example above i expect this to return 2 because 2 male. But it return 4 because distinct construction doesnt work.
I tried this but it doesnt work and count '1' in result:
sum(distinct case when gender = 'M' then 1 else NULL end) as 'M%'
It's easier to count from the distinct rows of the table.
Also, use SQLite's feature to treat boolean expressions as 1 for true and 0 for false so you can sum them instead of using CASE expressions:
SELECT date,
SUM(gender = 'M') [amount of males],
SUM(gender = 'F') [amount of females]
FROM (SELECT DISTINCT date, client_id, gender FROM tablename)
GROUP BY date
See the demo.
You seem to want conditional count(distinct):
select date,
count(distinct case when gender = 'M' then client_id end) as count_m,
count(distinct case when gender = 'F' then client_id end) as count_f
from t
group by date;

Sql conditional count

Can anyone help me with the sql and sqlite query for the below condition. To be specific, i wanted to show the merged count of 2 categories.
**Table**
Category Sub_category
A 1
A 2
A 2
B 1
C 1
C 1
C 2
D 1
D 1
D 1
D 2
D 3
**Required Output**
Category Sub_category Count **condition(not part of o/p just instruction)**
A 1 1 -
A 2+ 2 -
B 1 1 -
C 1 2 -
C 2+ 1 -
D 1 3 -
D 2+ 1 should contain the count of 2 and more
i am able to achieve the same using below:
select Category,
count(CASE WHEN Sub_category = 1 THEN Sub_category END) AS '1',
count(CASE WHEN Sub_category >= 2 THEN Sub_category END) AS '2+'
from table
however output is little different hence looking for the first output only.
**Output**
Category 1 2+
A 1 2
B 1 0
C 1 2
D 3 2
Thanks in advance!
You want:
select Category,
(case when sub_category = 1 then '1' else '2+' end) as sub_category,
count(*)
from table
group by Category,
(case when sub_category = 1 then '1' else '2+' end);
That is, you want to put the sub category groups on rows, not as columns.
You are just missing one column. Add the last count without a filtering to get the total:
select Category,
count(CASE WHEN Sub_category = 1 THEN Sub_category END) AS '1',
count(CASE WHEN Sub_category >= 2 THEN Sub_category END) AS '2+',
count(*)
from table
group by Category, count(CASE WHEN Sub_category = 1 THEN Sub_category END), count(CASE WHEN Sub_category >= 2 THEN Sub_category END), count(*)

Inner join without duplicate values from the left table?

I'm working with SQL Server, and I have 2 tables: Invoice and InvoiceService.
Invoice:
InvoiceID InvoiceDate InvoicePrice InvoicePaidAmount PatientID
----------------------------------------------------------------------------
1 01-01-2016 50 30 1
2 01-02-2016 100 100 2
InvoiceService:
ID InvoiceID ServiceName ServicePrice
-------------------------------------------------
1 1 Dermato 20
2 1 ophthalmo 30
3 2 General 100
My query:
select
ServiceName, ServicePrice, InvoiceID, InvoicePrice,
InvoicePaidAmount, PatientID
from
InvoiceService
inner join
Invoice on Invoice.InvoiceID = InvoiceService.InvoiceID
Result:
ServiceName ServicePrice InvoiceID InvoicePrice InvoicePaidAmount PatientID
Dermato 20 1 50 30 1
ophthalmo 30 1 50 30 1
General 100 2 100 100 2
I need to get non duplicate values from the left table :
when an invoice has more than 1 service I want that the invoice price and InvoicePaidAmount don't be repeated like this example:
ServiceName ServicePrice InvoiceID InvoicePrice InvoicePaidAmount PatientID
Dermato 20 1 50 30 1
ophthalmo 30 1 0 0 1
General 100 2 100 100 2
If I understand correctly, you want one invoice service to "really" match.
select s.ServiceName, s.ServicePrice, i.InvoiceID,
(case when seqnum = 1 then i.InvoicePrice else 0 end) as InvoicePrice,
(case when seqnum = 1 then i.InvoicePaidAmount else 0 end) as InvoicePaidAmount,
i.PatientID
from Invoice i join
(select s.*,
row_number() over (partition by s.InvoiceID order by s.id) as seqnum
from InvoiceService s
) s
on i.InvoiceID = s.InvoiceID