SQL JOIN and count without counting an ID twice - mysql

I am trying to join a table and get a count but I cannot count an ID twice in the table for the count.
Table 1:
ID animal
-- ------
1 dog
2 dog
3 cat
4 cat
5 dog
Table 2:
ID
--
2
2
3
5
5
I need to get a count of how many of each type of animal are in table 2. I can get it to join and change the ID to the type of animal and then get a count of each.
The issue is that each ID can only get counted once. So the expected output would be.
dog:2
cat:1
Where my output is
dog:4
cat:1

Try like below
select t1.animal, count( distinct t2.ID)
from table1 t1 join table2 t2 on t1.ID=t2.ID
group by t1.animal

You can try below using count distinct id
select b.animal,count(distinct a.id) from table2 a
inner join table1 b on a.id=b.id
group by b.animal

Try this:
SELECT t1.animal AS "Animal", COUNT(DISTINCT t1.ID) AS "No. of Animals"
FROM TABLE2 t2, TABLE1 t1
WHERE t2.ID = t1.ID
GROUP BY t1.animal

You can Try Nested Selects here.
SELECT
t.animal,
COUNT(t.ID) AS Count
FROM
(SELECT DISTINCT a.animal, b.ID FROM table1 a INNER JOIN table2 b ON a.ID = b.ID)t
GROUP BY t.animal
this is tested image

Related

Select from 1 table sum from 2 but 1 table has a AND condition

Thanks for assisting with the previous query (SQL Query that selects a column in table 1 and uses that to select sum in table 2) of SUM from 2 tables, I now have a additional Condition for 1 of the tables. I would like to add WHERE Group1 = 1 AND IN/OUT = 'OUT'
I have 3 tables,
Names ,Groups
Names ,Payments
Names ,Payments and IN/OUT
I want to only SUM the OUT Payments in Table 3, I am getting total payments only So FAR is have:
SELECT t1.name1, SUM(t2.sale2),SUM(t3.sale3)
FROM table1 t1 JOIN table2 t2 ON t1.name1 = t2.name2
JOIN table3 t3 ON t1.name1 = t3.name3
WHERE group1 = 1
GROUP BY t1.name1
i would also like to add a zero if there is no data to sum instead of removing the whole record, Currently if a name has no payments in Table 3 but has payments in table 2 it deletes the record.
Please check the query below =>
To Get OutPayment group by Name
SELECT t1.Names,SUM(t3.Payments) As OutPayment
FROM TABLE3 as t3
INNER JOIN TABLE1 as t1 ON t1.Names = t3.Names
INNER JOIN TABLE2 as t2 ON t1.Names = t2.Names
WHERE t1.GroupID = 1 AND t3.INOROUT=2 --INOROUT =2 is OUT and 1 is IN
GROUP BY t1.Names;
To Get TotalOutPayment
SELECT SUM(t3.Payments) As TotalOutPayment
FROM TABLE3 as t3
INNER JOIN TABLE1 as t1 ON t1.Names = t3.Names
INNER JOIN TABLE2 as t2 ON t1.Names = t2.Names
WHERE t1.GroupID = 1 AND t3.INOROUT=2; --INOROUT =2 is OUT and 1 is IN
Note: Code is in DBFiddle too Check the Demo Query Link

MySQL: Joining three tables and grouping one column

First of all, I'm an amateur on SQL. Here it is the example. From this three tables I would like to know how is called the teacher who makes more money with the classes:
Table1:
LessonName TeacherID
Maths 3
Biology 2
Biology 1
Geology 1
Table2:
Lesson PricePerClass
Maths 200
Biology 100
Geology 150
Table3:
IDTeacher TeacherName
1 Mike
2 John
3 Lauren
My main problem is that I don't know how to deal with the repeated values from the first table when I'm doing the triple join.
So far "I've made" this:
select IDTeacher, PricePerClass
from Table1 as T1
inner join Table2 as T2 on t1.LessonName = t2.Lesson
inner join Table3 as T3 on t1.TeacherId = t3.idTeacher
...
And I don't know how to keep going. I will have to group the t1.LessonName but every time I try to do it I get syntax errors. As you can see I'm pretty lost.
EDIT: My expected result would be something like:
IDTeacher TotalRevenue
1 250
Thanks a lot.
join the tables, group by teacher to aggregate and get the top row after you sort by the total descending:
select t3.IDTeacher, sum(t2.PricePerClass) TotalRevenue
from Table3 t3
inner join Table1 as t1 on t1.TeacherId = t3.IDTeacher
inner join Table2 as t2 on t2.Lesson = t1.LessonName
group by t3.IDTeacher
order by TotalRevenue desc limit 1
Note that this query does not return ties, if any.
SELECT t3.IDTeacher, t3.TeacherName, sum(t2.PricePerClass) from table1 t1
inner join table3 t3 on t1.TeacherID = t3.IDTeacher
inner join table2 t2 on t1.Lessonname = t2.Lesson
group by t3.TeacherName
order by sum(t2.PricePerClass) desc limit 1;

MySQL select a set of columns with more than one variation in another column

table looks like this:
id group name
1 1 A
2 1 A
3 2 A
4 2 B
5 3 A
I want to select the rows with more than one distinct names in the same group. The result should be the following:
id group name
3 2 A
4 2 B
Any idea how do achieve this?
You can get the groups with aggregation:
select group
from t
group by group
having min(name) <> max(name);
You can get the original rows using join, in, or exists:
select t.*
from t
where t.group in (select group
from t
group by group
having min(name) <> max(name)
);
Note: group is a lousy name for a column because it is a SQL keyword and a MySQL reserved word.
You could do it with a correlated subquery:
SELECT t1.id, t1.group, t1.name
FROM mytable AS t1
WHERE EXISTS (
SELECT * FROM mytable t2
WHERE t2.group=t1.group AND t2.name <> t1.name
);
Or you could do it by counting distinct names in the group:
SELECT t1.id, t1.group, t2.name
FROM mytable AS t1
INNER JOIN (
SELECT t2.group FROM mytable AS t2
GROUP BY t2.group HAVING COUNT(DISTINCT t2.name) > 1
) AS t2 USING (group);

Returning ids of a table where all values of other table exist with this id using all() or exists()

I have three tables with following data
Table 3 :
Table1_id Table2_id
1 1
1 2
1 3
2 1
2 3
3 2
Table 2 :
Table2_id Name
1 A
2 B
3 C
Table 1 :
Table1_id Name
1 P
2 Q
3 R
I have a problem where I need to return all table1_id's which have an entry for all Table2_ids's in Table 3.
ie. I want my output to be
Table1_id
1
I found a solution using count().
But is there a way to use all() or exists() to solve the query?
Using NOT IN with excluding LEFT JOIN in a subselect with a CROSS JOIN
select *
from table1
where Table1_id not in (
select t1.Table1_id
from table1 t1
cross join table2 t2
left join table3 t3 using (Table1_id, Table2_id)
where t3.Table1_id is null
)
VS using COUNT()
select table1_id
from table3
group by table1_id
having count(1) = (select count(1) from table2)
Explanation:
The CROSS JOIN
select t1.Table1_id
from table1 t1
cross join table2 t2
represents how table3 would look like, if every item from table1 would be related to every item from table2.
A (natural) left join with table3 will show us which relations really exists. Filtering by where t3.Table1_id is null (excluding LEFT JOIN) we get the missing relations. Using that result for the NOT IN clause, we get only table1 items that have no missing relation with table2.
You can use the following query:
SELECT DISTINCT t1.*
FROM Table2 AS t2
CROSS JOIN Table1 AS t1
WHERE NOT EXISTS (SELECT 1
FROM Table3 AS t3
WHERE t1.Table1_id = t3.Table1_id AND
t2.Table2_id = t3.Table2_id)
to get Table1 records not having a complete set of entries from Table2 in Table3. Then use NOT IN to get the expected result.
Here is a solution using EXISTS and INNER JOIN.
SELECT DISTINCT t3_out.Table1_id FROM Table3 t3_out
WHERE EXISTS( SELECT 1
FROM Table2 t2 INNER JOIN Table3 t3 ON t2.Table2_id = t3.Table2_id
WHERE t3.Table1_id = t3_out.Table1_id
HAVING COUNT(DISTINCT t2.Table2_id) = 3 )

Select count with join in SQL query

How can I check how many products added by a,b,c,d respectively by using a query?
table1
admin_id admin_name
3 a
4 b
5 c
6 d
table2
admin_id products
3 pDeal
3 pSeal
4 pAeal
5 pZeal
6 pXeal
3 pHeal
6 pPeal
You need a simple JOIN and a COUNT query:
SELECT table1.admin_name, COUNT(*) as cnt
FROM
table1 INNER JOIN table2
ON table1.admin_id = table2.admin_id
GROUP BY
table1.admin_name
Try this...
SELECT a.admin_name, COUNT(b.products) as 'CountOfProducts'
FROM table1 a INNER JOIN table2 b ON a.admin_id = b.admin_id
GROUP BY a.admin_name
Use this
SELECT adm.admin_name,COUNT(pdr.products) as ProductCnt
FROM table1 AS adm
JOIN table2 AS pdr
ON adm.admin_id = pdr.admin_id
GROUP BY adm.admin_id;
SELECT t1.admin_name, COUNT(t2.products)
FROM table1 AS t1 LEFT JOIN table2 AS t2 ON t1.admin_id = t2.admin_id
WHERE 1
GROUP BY t2.admin_id
The LEFT JOIN will ensure the cases when table2 doesn't have any record for some admin of table 1.
You can use an inner-select like this:
SELECT
table1.admin_name,
(SELECT COUNT(*)
FROM table2
WHERE table1.admin_id = table2.admin_id) As cnt
FROM
table1;