Equivalent of excel COUNTIFS - sql

I am trying to get a COUNTIFS from excel type of result
Here is the products table:
Name Product
john car
john football
john image
max food
max tv
max laptop
max image
max image
max image
alex tv
alex laptop
alex image
alex cake
alex cake
alex cake
alex cake
alex car
The output should be:
Name Product Number of products per person Number of products of the same type
john car 1 2
john football1 1
john image 1 5
max food 1 1
max tv 1 2
max laptop 1 2
max image 3 5
alex tv 1 2
alex laptop 1 2
alex image 1 5
alex cake 4 4
alex car 1 2
Number of products per person is count of products by name by product
and Number of products of the same type is based on the total count by product
for example image is repeated 3 times for max so in col C the answer is 3 but it there 5 times in the table so answer in col D is 5
I tried but not getting the correct answer:
SELECT
name,
product,
COUNT(*),
COUNT(*) OVER (PARTITION BY product),
from products
GROUP BY 1,2
ORDER BY 1

You are quite close. You need to sum the COUNT(*). You can do this directly in the aggregation query:
SELECT name, product,
COUNT(*),
SUM(COUNT(*)) OVER (PARTITION BY product)
FROM products
GROUP BY 1, 2
ORDER BY 1

#standardSQL
SELECT name, product, product_per_person,
SUM(product_per_person) OVER(PARTITION BY product) product_total
FROM (
SELECT
name,
product,
COUNT(*) product_per_person
FROM `project.dataset.products`
GROUP BY 1,2
)
ORDER BY 1
if to apply to your sample data - result should be
Row name product product_per_person product_total
1 alex cake 4 4
2 alex car 1 2
3 alex image 1 5
4 alex laptop 1 2
5 alex tv 1 2
6 john car 1 2
7 john football 1 1
8 john image 1 5
9 max food 1 1
10 max image 3 5
11 max laptop 1 2
12 max tv 1 2

use group by name and product
SELECT name,
product,
COUNT(*),
COUNT(*) OVER (partition by product)
from products
GROUP BY name,product
ORDER BY 1

Related

count different column values after grouping by

Consider this table:
id name department email
1 Alex IT blah#gmail.com
1 Alex IT blah#gmail.com
2 Jay HR jay#gmail.com
2 Jay Marketing zou#gmail.com
If I group byid,name and count I get:
id name count(*)
1 Alex 2
2 Jay 2
With this query:
select id,name,count(*) from tb group by id,name;
However I would like to count only records that diverge from department,email, so as to have:
id name count(*)
1 Alex 0
2 Jay 1
This time the count for the first group 1,Alex is 0 because department,email have the same values (duplicated) , on the other hand 2,Jay is one because department,email has one different value.
If you meant "two different values" for "Jay", you can use distinct:
select id,name,count(*) from (SELECT distinct * FROM tb) group by id,name;
You can use count(*) - 1 to get similar results in your question.

merge two rows into one sql

this is my table schema, total_hours column is the result of a sum function.
Id name client total_hours
1 John company 1 100
1 John company 2 200
2 Jack company 3 350
2 Jack company 2 150
I want to merge the rows with similar ID into one row, looking like this.
Id name client_a total_hours_a client_b total_hours_b
1 John company 1 100 company 2 200
2 Jack company 3 350 company 2 150
I tried to use pivot but this function does not seem to exist in Dbeaver. Here is my query
SELECT
client
,name
,sum(hours) AS total_hours
FROM pojects
GROUP BY client, name;
Thanks in advance if anyone could be of any help.

select only one row in sum and group

i have a table TB_Orders , i save orders in thatl ,ike below :
userid
factorid
productname
economy
vip
count
1
A-123
name1
13000
18000
3
1
A-123
name2
9000
13000
4
2
A-124
name2
2000
5000
2
For example, user 1: has registered two orders with invoice number A-123.
And user 2 has only registered one order
I want to report as follows:
userid
factorid
total economy
total vip
total count
1
A-123
21000
31000
7
2
A-124
2000
5000
2
thanks for your help
This is an aggregation query:
select userid, factorid, sum(economy), sum(vip), sum(count)
from tb_orders
group by userid, factorid;
Aggregation is a very basic part of SQL functionality. If you don't recognize it, I would suggest that you brush up on your SQL skills with a tutorial, book, or something like that.

Grouping and ordering by value, alphabet and frequency based on common value

So I am working with MS Access and have this participant list With three columns age, name and age_group and want it first ordered by name and then by age and also by frequency of the age_group based on the same name. For example:
age | age_group |name
----------------------
1 0-1 Jeff
10 10=< Dave
10 10=< Dave
5 5-7 Carl
2 2-4 Sam
3 2-4 Carl
4 2-4 Sam
2 2-4 Sam
5 5-7 Carl
6 5-7 Jeff
7 5-7 Dave
10 10=< Jeff
8 8-9 Jeff
So it first would look like this, ordered by name and by age
----------------------
10 10=< Jeff
8 8-9 Jeff
6 5-7 Jeff
1 0-1 Jeff
10 10=< Dave
10 10=< Dave
7 5-7 Dave
5 5-7 Carl
5 5-7 Carl
3 2-4 Carl
4 2-4 Sam
2 2-4 Sam
2 2-4 Sam
And finally by age_group frequency in descending order 10=<, 8-9, 5-7, 2-4, 0-1, based on the same name. Frequency meaning how many times the age group is present in any subset of name. For example age group 10=< is present two times in subset Dave.
age | age_group |name
----------------------
10 10=< Dave
10 10=< Dave
7 5-7 Dave
10 10=< Jeff
8 8-9 Jeff
6 5-7 Jeff
1 0-1 Jeff
5 5-7 Carl
5 5-7 Carl
3 2-4 Carl
4 2-4 Sam
2 2-4 Sam
2 2-4 Sam
Is this possible to do in SQL or VBA? I get the first one to work with:
SELECT participants.name, participants.age_group, participants.age, *
FROM participants
ORDER BY participants.name, participants.age DESC;
But I am totally lost in performing the second step...
Would appreciate if you could help me out.
This fancy SQL will provide the grouped output:
SELECT
T3.age, T3.age_group, T3.name
FROM
Participants As T3
INNER JOIN
(SELECT [age] * 1000 + Count(*) AS rating, T.name
FROM participants AS T
INNER JOIN
(SELECT Max(participants.age) AS maxage, participants.name
FROM participants
GROUP BY participants.name) AS T2
ON (T.age = T2.maxage) AND (T.name = T2.name)
GROUP BY T.name, T.age
ORDER BY [age] * 1000 + Count(*) DESC) AS T4
ON T3.name = T4.name
ORDER BY T4.rating Desc, T3.age Desc
Output:
Try this:
select p1.name, p2.age_group, p2.age
from participants as p1
left join (select name, age_group, count(1) as freq from participants group by name, age_group) as p2
on p1.name= p2.name and p1.age_group = p2.age_group
order by name,age, p2.freq desc
Access:
select p1.name, p1.age_group, p1.age
from participants as p1
left join
(select name, age_group, count(1) as freq
from participants group by name, age_group) as p2
on p1.name= p2.name and p1.age_group = p2.age_group
order by p1.name, p1.age, p2.freq desc
Access output:

SQL query to get only rows match the condition based on two separated columns under one 'group by'

The simple SELECT query would return the data as below:
Select ID, User, Country, TimeLogged from Data
ID User Country TimeLogged
1 Samantha SCO 10
1 John UK 5
1 Andrew NZL 15
2 John UK 20
3 Mark UK 10
3 Mark UK 20
3 Steven UK 10
3 Andrew NZL 15
3 Sharon IRL 5
4 Andrew NZL 25
4 Michael AUS 5
5 Jessica USA 30
I would like to return a sum of time logged for each user grouped by ID
But for only ID numbers where both of these values Country = UK and User = Andrew are included within their rows.
So the output in the above example would be
ID User Country TimeLogged
1 John UK 5
1 Andrew NZL 15
3 Mark UK 30
3 Steven UK 10
3 Andrew NZL 15
First you need to identify which IDs you're going to be returning
SELECT ID FROM MyTable WHERE Country='UK'
INTERSECT
SELECT ID FROM MyTable WHERE [User]='Andrew';
and based on that, you can then filter to aggregate the expected rows.
SELECT ID,
[User],
Country,
SUM(Timelogged) as Timelogged
FROM mytable
WHERE (Country='UK' OR [User]='Andrew')
AND ID IN( SELECT ID FROM MyTable WHERE Country='UK'
INTERSECT
SELECT ID FROM MyTable WHERE [User]='Andrew')
GROUP BY ID, [User], country;
So, you have described what you need to write almost perfectly but not quite. Your result table indicates that you want Country = UK OR User = Andrew, rather than AND
You need to select and group by, then include a WHERE:-
Select ID, User, Country, SUM(Timelogged) as Timelogged from mytable
WHERE Country='UK' OR User='Andrew'
Group by ID, user, country