MySQL Select statement based on multiple joins - mysql

I have a select statement that requires me to join multiple tables (4 tables).
My tables are the following:
Teams
Team_User
Tournament_User
Tournaments
I need to get the teams from a certain tournament. My logic is at it follows:
In Tournament_User table i can find the users that are in a tournament. In Team_User i can find the users that are in a team.
To get the teams from a certain tournament I tried the following query:
SELECT t.id FROM Teams t
JOIN Team_User tu on tu.team_id = t.id
JOIN Tournament_User tru on tru.user_id = tu.user_id
JOIN Tournaments tr on tr.id = tru.tournament_id
WHERE tr.id = "tournamentId";
It gets me the correct teams, but it duplicates them.
I also added DISTINCT which it gets me the correct teams and without duplicating them, but I wonder if I can retrieve the records as expected using only joins and without DISTINCT.
Also, my records can't contain duplicates and there are no duplicates, I somehow managed to bring them duplicated based on my query.

I presume there is a Users table in your schema. There is a many-to-many relation between Teams and Users as well as a many-to-many relation between Users and Tournaments. That means each tournament will be related to many users, which in turn means that even if all users are from the same team, your query result will have each team as many times as there are users from it in the given tournament. The nature of the relations between these tables necessitates that you use DISTINCT.

Related

Query to Pull Data from 2 Junction Tables

I'm creating a database for comics. Right now I have 3 main tables (comics, publishers, people) and 3 junction tables (person2comic, publisher2comic and person2publisher). I want to be able to have a search form that allows searching by any combination of title, issue number, publisher, and person. When referencing only one junction table, I use a variation of this depending on what's being searched for:
SELECT comicTitle, comicIssue, firstName, lastName
FROM person2comic
JOIN comics ON comics.comicID = person2comic.comicID
AND comics.comictitle LIKE "%walk%" ;
If someone were to search by title, publisher and person, I'm not sure how to set up the statement since it would require using two of the junction tables. Would it be a nested query situation or something else?
You can have arbitrarily many joins. Not exactly sure on all of your column names, but this should roughly work:
SELECT *
FROM people
JOIN person2comic p2c ON people.id = ptc.person
JOIN comic ON p2c.comic = comic.id
JOIN publisher2comic pub2c ON comic.id = pub2c.comic
JOIN publisher ON pub2c.publisher = publisher.id
Also note that your schema may be inefficient if you relationships all aren't many-to-many. See my comment.

Get records not in table (MySQL)

I have three tables: Member, Meeting and Member_Meeting. The names alone should give away what they contain. Member is for registered members, Meeting is for past and future meetings and Member_Meeting is for members who have or will be attending meetings. I can use inner joins to get data in both tables, left joins to get data in both but also on the left, right joins to get data in both but also on the right and (full) outer joins to get data from both and right and left. What I need however is data that only exists in Member but not in Member_Meeting. In other words, I need to get all the members that exist but have not ever attended a meeting and therefore do not have a record in the Member_Meeting. What I need is sort of like a left join or a right join but without what the tables have in common.
There's two ways of doing this. The first is to do a subquery using NOT IN():
SELECT * FROM Member WHERE ID NOT IN(SELECT DISTINCT MemebrID FROM Member_Meeting)
The other option is to do a LEFT JOIN and then filter on the null values
SELECT Member.* FROM Member
LEFT JOIN Member_Meeting ON Member.ID = Member_Meeting.MemberID
WHERE Member_Meeting.MemberID IS NULL

MySQL Join with many (fields) to one (secondary table) relationship

I have a query I need to perform on a table that is roughly 1M records. I am trying to reduce the churn, but unfortunately there is a UNION involved (after i figure this join out), so that may be a question for another day.
The records and data I need to get reference 3 fields in a table that need each pull a description from another table and return it in the same record, but when i do the Inner join i was thinking, it either returns only 1 field fromt he other table, or multiple records from he original table.
Here are some screen shots of the tables and their relationship:
Primary table containing records (1 each) with the physician record I want to pull, including up to 3 codes that can be listed in the "taxonomy" table.
Secondary table containing records (1 each) with the "Practice" field I want to pull.
A Quick glance of the relationship i'm talking about
I presume that if perform an inner join matching the 3 fields in the physicians table, that it will have to iterate that table multiple times to pull each taxonomy code .. but I still can't even figure the syntax to easily pull all of these codes instead of just 1 of them.
i've tried this:
SELECT
taxonomy_codes.specialization,
physicians.provider_last_name,
physicians.provider_first_name,
physicians.provider_dba_name,
physicians.legal_biz_name,
physicians.biz_practice_city
FROM
taxonomy_codes
INNER JOIN physicians ON physicians.provider_taxonomy_code_1 = taxonomy_codes.taxonomy_codes OR physicians.provider_taxonomy_code_2 = taxonomy_codes.taxonomy_codes OR physicians.provider_taxonomy_code_3 = taxonomy_codes.taxonomy_codes
First, the query churns a lot and it only returns one taxonomy specialty result which I presume is because of the OR in the join statement. Any help would be greatly appreciated.
Thank you,
Silver Tiger
You have to join the taxonomy_codes table multiple times:
SELECT p.provider_last_name, p...., t1.specialization as specialization1, t2.specialization as specialization2, t3.specialization as specialization3
FROM physicians p
LEFT JOIN taxonomy_codes t1 ON t1.taxonomy_codes = provider_taxonomy_code_1
LEFT JOIN taxonomy_codes t2 ON t2.taxonomy_codes = provider_taxonomy_code_2
LEFT JOIN taxonomy_codes t3 ON t3.taxonomy_codes = provider_taxonomy_code_3

mysql table problem?

i have these two tables tables for a chatting app
users{user_id,username,pictures}
chat_data(con_id, chat_text}
i used this sql query
SELECT c.chat_text, u.username
FROM chat_data c, users u
WHERE c.con_id =1
but its giving me duplicate results, when i know thiers only row with the con_id =1, what is the problem with the query!! :))
You need to "join" the tables to avoid duplicates. For example
SELECT c.chat_text, u.username
FROM chat_data c, users u
WHERE c.con_id =1
and u.id = c.user_id
You can read a bit about relational algebra which is the theory behind relational databases.
The users and chat_data tables should be JOINED in order to get a unique tuple as result.
Since users and chat_data cannot be joined, you simply get Cartesian product of the two tables.
Cartesian Products
If two tables in a join query have no
join condition, then Oracle Database
returns their Cartesian product.
Oracle combines each row of one table
with each row of the other. A
Cartesian product always generates
many rows and is rarely useful. For
example, the Cartesian product of two
tables, each with 100 rows, has 10,000
rows. Always include a join condition
unless you specifically need a
Cartesian product. If a query joins
three or more tables and you do not
specify a join condition for a
specific pair, then the optimizer may
choose a join order that avoids
producing an intermediate Cartesian
product.
Refer: http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/queries006.htm
With a query like that, you will get as many rows in the results as there are rows in the table users.
It's because of the type of join the SQL is doing. Is it returning a row for each user you have? This is what I expect it is doing, i.e. if you have 2 users John and Jack then are you getting a row for both of these users being returned?
Are you just trying to get the data related to the users involved in a conversation? If so you need some link between the 2 tables, like foreign key references from the chat_data table referencing users.
As previously stated, you're missing a link between the two tables. If you are trying to retrieve the user associated to a particular chat you will need to add a foreign key reference in chat_data that references user.user_id. But if you are trying to get multiple users associated to a chat you would need to add a new table. Your new tables would look something like this:
users{user_id,username,pictures}
chat_data(con_id, chat_text}
user_chat(user_id, con_id) //By adding this new table you can have multiple users per chat
The the query would look something like
SELECT u.username, c.chat_text
FROM users u, chat_data c, user_chat uc
WHERE u.id = uc.id
AND c.con_id = uc.con_id

Scalable way of doing self join with many to many table

I have a table structure like the following:
user
id
name
profile_stat
id
name
profile_stat_value
id
name
user_profile
user_id
profile_stat_id
profile_stat_value_id
My question is:
How do I evaluate a query where I want to find all users with profile_stat_id and profile_stat_value_id for many stats?
I've tried doing an inner self join, but that quickly gets crazy when searching for many stats. I've also tried doing a count on the actual user_profile table, and that's much better, but still slow.
Is there some magic I'm missing? I have about 10 million rows in the user_profile table and want the query to take no longer than a few seconds. Is that possible?
Typically databases are able to handle 10 million records in a decent manner. I have mostly used oracle in our professional environment with large amounts of data (about 30-40 million rows also) and even doing join queries on the tables has never taken more than a second or two to run.
On IMPORTANT lessson I realized whenever query performance was bad was to see if the indexes are defined properly on the join fields. E.g. Here having index on profile_stat_id and profile_stat_value_id (user_id I am assuming is the primary key) should have indexes defined. This will definitely give you a good performance increaser if you have not done that.
After defining the indexes do run the query once or twice to give DB a chance to calculate the index tree and query plan before verifying the gain
Superficially, you seem to be asking for this, which includes no self-joins:
SELECT u.name, u.id, s.name, s.id, v.name, v.id
FROM User_Profile AS p
JOIN User AS u ON u.id = p.user_id
JOIN Profile_Stat AS s ON s.id = p.profile_stat_id
JOIN Profile_Stat_Value AS v ON v.id = p.profile_stat_value_id
Any of the joins listed can be changed to a LEFT OUTER JOIN if the corresponding table need not have a matching entry. All this does is join the central User_Profile table with each of the other three tables on the appropriate joining column.
Where do you think you need a self-join?
[I have not included anything to filter on 'the many stats'; it is not at all clear to me what that part of the question means.]