INNER JOIN if table 1 has 2 rows matching in table 2 - mysql

I don't exactly know how to word this question correctly, so I'll start with the data because I think it will make more sense that way.
Starting with these two tables:
Table 1:
user_id | equipment_id
------ | ------
1 | 2
1 | 3
1 | 6
2 | 2
2 | 6
Table 2:
equipment_id | exercise_id
------ | ------
2 | 1
3 | 2
6 | 2
I would like to create this third table:
Table 3:
user_id | exercise_id
------ | ------
1 | 1
1 | 2
2 | 1
It seems like a simple INNER JOIN to get the data, but I'm running into trouble with the second row. I only want that row to show up if user_id 1 has both pieces of equipment listed in Table 2. If either piece of equipment is missing, I don't want the data inserted as shown by user_id 2. I also want to make sure I don't get two instances of user_id 1 for each piece of equipment.
This is the code I have so far:
INSERT INTO Table3 (user_id, exercise_id)
SELECT user_id, exercise_id
FROM Table1
INNER JOIN Table2
ON Table2.equipment_id = Table1.equipment_id
The result I get is this with the rows that need to be removed indicated:
Table 3:
user_id | exercise_id
------ | ------
1 | 1
1 | 2
1 | 2 <--- duplicate of row above
2 | 1
2 | 2 <--- user 2 doesn't have equipment 3, so shouldn't be included
Any help on limiting the results would be greatly appreciated. Thank you!

If I understand correctly, you want to retrieve all the exercises for a user where all the equipment required for that exercise is "available" to the user. I've put some code over at rextester.com/AYRE74108. The important part of that looks like this:
select distinct
t1.user_id,
t2.exercise_id
from
table_1 t1
JOIN table_2 t2 ON
t1.equipment_id = t2.equipment_id
where
not exists
(select 1
from
table_2 t2b
where
t2b.exercise_id = t2.exercise_id
AND not exists (select 1
from
table_1 t1b
where
t2b.equipment_id = t1b.equipment_id
AND t1.user_id = t1b.user_id)
)
To explain the logic: I begin with the standard join and distinct. But then I require that there NOT EXIST any piece of equipment required for the exercise such that that user/equipment combination does NOT EXIST. This is equivalent to saying the user has to have "available" (listed in table 1) all the equipment required for the exercise.
Or schematically: "ALL X are Y" === "NO X is such that Not Y".

I feel that the last row of your output should not be 2 | 2 but 1 | 2.
Also using distinct will ensure that there will be no duplicate rows.
SELECT DISTINCT user_id, exercise_id
FROM Table1
INNER JOIN Table2
ON Table2.equipment_id = Table1.equipment_id
Edit - The mistake in the question threw me off. This should work.
SELECT user_id, table2.exercise_id , sum(table2.equipment_id), sum(b.equipment_id)
FROM Table1
INNER JOIN Table2
ON Table2.equipment_id = Table1.equipment_id
inner join table2 as b
on table2.exercise_id = b.exercise_id
group by user_id, table2.exercise_id
having sum(table2.equipment_id)= sum(b.equipment_id)

Related

MySql Join and count number of records

I have two tables
tbl_groups:
id | name
----------------
1 | BSCS
2 | BSIT
3 | BBA
tbl_students:
id | name | group_id
-------------------------------
1 | Student Name | 1
2 | Student 2 | 1
3 | Student 3 | 2
I want to show groups details: group name and number of students in a particular group,
I am using this query but it shows groups that has students. it does not show group with 0 students.
select tb2.id, tb2.name, count(*) from tbl_students tb1 JOIN tbl_groups tb2 ON tb1.group_id = tb2.id
How do I show all groups, please give me some idea
EDIT:
if I use above query I get following result:
id | name | count(*)
-------------------------------
1 | Student Name | 2
2 | BSIT | 1
(it doest show 3rd group because there are 0 students, I want to show this groups also).
Just use a left join:
select tb2.id, tb2.name, count(tb1.id) as no_std
from tbl_groups tb2
LEFT JOIN tbl_students tb1 ON tb2.id = tb1.group_id
group by tb2.id, tb2.name
See it working live here: http://sqlfiddle.com/#!9/2282a3/5
I would just use a correlated subquery to get the count of students in each group, like so:
select
g.*,
(select count(*) from tbl_students s where s.group_id = g.id) no_students
from tbl_groups g
This does not filter out groups that have no students (it will give a count of 0 instead). And with an index on tbl_students(group_id), this should be as efficient as it gets (this index is already there if you set up a foreign key constraint on that column - as you should have).

MySQL Error to selecting data

I have two column one column associated with another...
Table:base_data
id |---name----|-----des
1 | some name1 | The description1
2 | some name2 | The description2
Table: photos
id |---p_id----|-----photo
1 | 1 | img1s.jpg
2 | 1 | img1w.jpg
3 | 2 | img2.jpg
4 | 2 | img14.jpg
5 | 2 | img15.jpg
I want to select all data from table 1(base_data) and one row from associated row from photos: table how can I do that ????
I don't want to select by greatest n per group I want to select all data from the first table and only one row of the second table which matches with the first table row id, just first match not other.
The Result I want...
id |---name----|---des----|---p_id----|---photo----|
1 | some name |the des..1| 1 | img1s.jpg|
2 | some name |the des..2| 2 | img2.jpg|
I suppose you want to associate base_data with the first photo taken, which should be the one with the lowest photos.id. In MySQL, you could write this as follows: Create an intermediate query which gives - for any p_id - the corresponding record with the lowest id. Then, left join base_data with this intermediate query result. Hope there are not to many typos in it :-) :
select b.id, p2.photo
from base_data b left join
(select p.photo, p.p_id, min(id) from photos p group by p.p_id) p2 on b.id = p2.p_id
If you want the alphanumerically lowest photo name, in MySQL you can do this:
select
t1.*,
t2.photo
from
base_data as t1
left join (
select
p_id,
min(photo) as photo
from
photos
group by
p_id
) as t2 on t2.p_id = t1.id;

Are multiple joins on the same table possible?

I have a question about getting data from a table with multiple joins.
Table 1 holds the information (name and amount) and table 2 contains the combinations.
A row in table 2 contains the id's which correspond to the ID's from table 1.
I try to get the information out of table 1 based on the corresponding id's in table 2.
Table1
Id | Name | Amount
--------------------
4 | Test 1 | 50
5 | Test 2 | 60
6 | Test 3 | 70
7 | Test 4 | 80
Table2
id | PriceId | MaterialId | ServiceId
-------------------------------------
1 | 4 | 5 | 6
2 | 4 | 5 | 7
Query
To get an idea what I try to reach:
SELECT * FROM Table1 a
LEFT JOIN Table2 b ON a.Id = b.PriceId
LEFT JOIN Table2 c ON a.Id = c.MaterialId
LEFT JOIN Table2 d ON a.Id = d.ServiceId
GROUP BY a.Id
So I try to get the name and amount from table 1 corresponding with the Id's in table 2, Thus:
When I select everything from Table 2 with ID 1 then I try to get the following:
Table 2 with ID 1: PriceId = 4, MaterialId = 6, ServiceId = 6
Table 1: Test 1, Test 2, Test 3
Because PriceId 4 is corresponding with Test 1, and MaterialID 6 is corresponding with Test 2 etc etc.
Hopefully above is clearly. Any help is appreciated!
It seems you are approaching it from the wrong direction. What you really want is:
SELECT t2.PriceId AS PriceId,
t2.ServiceId AS ServiceId, t1p.Name AS PriceName,
t1m.Name AS MaterialName, t1s.Name AS ServiceName
FROM Table2 t2
LEFT JOIN Table1 t1p ON t2.PriceId = t1p.Id
LEFT JOIN Table1 t1m ON t2.MaterialId = t1m.Id
LEFT JOIN Table1 t1s ON t2.ServiceId = t1s.Id
See this fiddle.
Yes you can use that way ...
See my example :
select * from movies
inner join relationship as r1 on movies.id=r1.movie_id
inner join relationship as r2 on movies.id=r2.movie_id
where r1.Taxonomy_id ="xyz"
and r2.Taxonomy_id="abc"
GROUP BY movies.id
This will work for you. I had done this in one of my project

Count(*) with a join

This is probably very simple, but for some reason I am pulling a blank on this one..
I want to join two tables and get the total occurrences of a column in one table within another table.
Table1
id | company
------------
1 | companyA
2 | companyB
3 | companyC
Table2
id | company_id
------------
1 | 2
2 | 2
3 | 1
4 | 2
5 | 3
The result should be:
company | count(*)
------------------
companyA| 1
companyB| 3
companyC| 1
I can't seem to get the count portion correct. I was thinking that it would be something like:
SELECT Table1.company, count(*)
FROM Table1 JOIN Table2 ON
Table1.id = Table2.company_id
GROUP BY Table1.company;
Revised: The problem is actually that companyA and companyB come up correctly, but it's not showing companyC. I went through and double checked that there are matches in the fields for companyC which there were.
it should be Table2.company_id that you are joining with and not Table2.id
SELECT Table1.company, count(*)
FROM Table1
INNER JOIN Table2
ON Table1.id = Table2.company_id -- <<== here
GROUP BY Table1.company;
you must define an INDEX (probably UNIQUE) on column company of table for faster performance since you are grouping it with company
UPDATE 1
SELECT Table1.company, count(Table2.company_id)
FROM Table1
LEFT JOIN Table2
ON Table1.id = Table2.company_id -- <<== here
GROUP BY Table1.company;
SQLFiddle Demo

SELECTING SUM based on conditional if from another table

Database: mysql > ver 5.0
table 1: type_id (int), type
table 2: name_id, name, is_same_as = table2.name_id or NULL
table 3: id, table2.name_id, table1.type_id, value (float)
I want to sum values, and count values in table 3 where table2.name_id are same and also include the values of id where is_same_is=name_id. I want to select all data in table3 for all values in table2.
Apologize if my question is not very clear, and if it has already been answered but I am unable to find a relevant answer. Or dont exactly know what to look for.
[data]. table1
id | type
=========
1 | test1
2 | test2
[data].table2
name_id | name | is_same_as
==============================
1 | tb_1 | NULL
2 | tb_2 | 1
3 | tb_3 | NULL
4 | tb_4 | 1
[data].table3
id | name_id | type_id | value
======================================
1 | 1 | 1 | 1.5
2 | 2 | 1 | 0.5
3 | 2 | 2 | 1.0
output:
name_id| type_id|SUM(value)
=======================================================
1 | 1 |2.0 < because in table2, is_same_as = 1
2 | 2 |1.0
I think the following does what you want:
select coalesce(t2.is_same_as, t2.name_id) as name_id, t3.type_id, sum(value)
from table_3 t3 join
table_2 t2
on t3.name_id = t2.name_id
group by coalesce(t2.is_same_as, t2.name_id), t3.type_id
order by 1, 2
It joins the table on name_id. However, it then uses the is_same_as column, if present, or the name_id if not, for summarizing the data.
This might be what you are looking for: (I haven't tested it in MySQL, so there may be a typo)
with combined_names_tab (name_id, name_id_ref) as
(
select name_id, name_id from table2
union select t2a.name_id, t2b.name_id
from table2 t2a
join table2 t2b
on (t2a.name_id = t2b.is_same_as)
)
select cnt.name_id, t3.type_id, sum(t3.value) sum_val
from combined_names_tab cnt
join table3 t3
on ( cnt.name_id_ref = t3.name_id )
group by cnt.name_id, t3.type_id
having sum(t3.value) / count(t3.value) >= 3
Here's what the query does:
First, it creates 'combined_names_tab' which is a join of all the table2 rows that you want to GROUP BY using the "is_same_as" column to make that determination. I make sure to include the "parent" row by doing a UNION.
Second, once you have those rows above, it's a simply join to table3 with a GROUP BY and a SUM.
Note: table1 was unnecessary (I believe).
Let me know if this works!
john...