MySQL Join different tables - mysql

I am trying to join the following tables with the following code, but I can't join the last columns.
Table:magazine
id_mag **mag_name** id_freq
Table:frequency
id_freq **freq_name**
Table:copy
id_mag **id_copy** **copy_date** copy_price copy_page_number
Table:article
id_art **art_name** **art_page_number**
Table:copy_art
id_mag **id_copy** id_art article_page_num
I want to show a table with the following columns. The columns in the tables magazine, frequency, copy, article & copy_art that have ** ** are the ones I am interested in to be showed:
mag_name freq_name id_copy copy_date art_name art_page_number
I got the following table with this code:
SELECT * FROM magazine
JOIN frequency ON magazine.id_freq = frequency.id_freq
JOIN copy_art ON revista.id_mag=copy_art.id_mag
JOIN article ON copy_art.id_art=article.id_art
JOIN copy ON copy_art.id_copy=copy.id_copy;
Here is the translation for the name of each column that appears in the image:
id_rev = id_mag
nom_rev = mag_name
id_frec = id_freq
nom_frec = freq_name
id_rev = id_mag
id_ejem = id_copy
id_art = id_art
num_pag = article_page_num
nom_art = art_name
num_pag_art = art_page_number
fecha_ejem = copy_date
precio = copy_price
My doubt is the following:
What should I do in order to have the table with?
mag_name freq_name id_copy copy_date art_name article_page_num
Thanks a lot for your kindly support!

If you only want a few columns in the output, then you have to list which columns you do want. The key structure of the data is unclear (meaning it isn't clear which columns are the primary keys of each table); you have the id_mag and id_copy columns both appearing in copy and copy_art and it isn't entirely clear whether they're a composite key or id_copy is sufficient. Given that we don't have that information, we'll have to take your SELECT statement and its joins as gospel, but I'm not convinced that's correct.
You wrote:
SELECT *
FROM magazine
JOIN frequency ON magazine.id_freq = frequency.id_freq
JOIN copy_art ON revista.id_mag=copy_art.id_mag
JOIN article ON copy_art.id_art=article.id_art
JOIN copy ON copy_art.id_copy=copy.id_copy;
This collects all the columns from all the tables mentioned, which is wasteful. So, you need to specify which columns you do want:
SELECT m.mag_name, f.freq_name, c.id_copy, c.copy_date, a.art_name, a.art_page_number
FROM magazine AS m
JOIN frequency AS f ON m.id_freq = f.id_freq
JOIN copy_art AS y ON m.id_mag = y.id_mag
JOIN article AS a ON y.id_art = a.id_art
JOIN copy AS c ON y.id_copy = c.id_copy;
I'm not entirely sure that you need the copy_art table in the query, but I'm assuming you know your data better than I do.

You have to make sure that one of the first tables has got a foreign key for the articulo table to join that as well.
If you add that (For example in the revista table), you can make a JOIN over all tables with something like this:
SELECT * FROM revista
JOIN frecuencia ON revista.id_frec = frecuencia.id_frec
JOIN ejemplar ON revista.id_rev = ejemplar.id_rev
JOIN articulo ON revista.id_art = articulo.id_art;
See this fiddle for an example (I query * here, you can change that to just the columns that you need).

Related

mysql check multiple column in on statement

I am stuck in 1 left join query in which I want to check multiple columns in on statement.
By default in the database, some column is null which I want to check in the on statement.
Now the issue is when I run a query using the OR operator it only runs the 1st condition and the rest are skipped.
If I use AND operator it throws an error.
So is there any way to get data from multiple conditions?
Here is my query:
$data = "SELECT
b.book_name, b.book_id,
b.cats_id, b.cats_id1,
b.cats_id2, b.cats_id3,
b.cats_id4, b.cats_id5,
b.cats_id6,
b.book_rating,
b.book_author,
b.book_stock,
b.book_publisher,
b.book_front_img,
b.book_status,
p.publisher_id,
p.publisher_name,
a.author_id,
a.author_name,
cat.cats_id,
cat.cats_name,
cat.cats_status
FROM
`books` AS b
LEFT JOIN `publisher` AS p
ON b.book_publisher = p.publisher_id
LEFT JOIN `author` AS a
ON b.book_author = a.author_id
LEFT JOIN categorys As cat
ON b.cats_id = cat.cats_id
OR b.cats_id1 = cat.cats_id
OR b.cats_id2 = cat.cats_id
OR b.cats_id3 = cat.cats_id
OR b.cats_id4 = cat.cats_id
OR b.cats_id5 = cat.cats_id
OR b.cats_id6 = cat.cats_id
GROUP BY
b.book_name
HAVING
cat.cats_name = '$search_data'
AND b.book_status = 1
ORDER BY
$sorting
LIMIT $offset, $page_limit"
You probably don't have more than one author displayed for your multi-author books either. You are misusing MySQL's notorious nonstandard extension to GROUP BY.
To troubleshoot this kind of query, disable that extension with SET sql_mode = CONCAT_WS(',',##sql_mode, 'ONLY_FULL_GROUP_BY'), then try your query again. You'll need more terms in your GROUP BY clause.
It looks like each books row has multiple category id columns. And it looks like you want to display information from your categorys table for each of them.
Use GROUP BY b.book_id, p.publisher_id, a.author_id, cats.cats_id to prevent MySQL's bizarro handling of GROUP BY from concealing your data.
I must add this: your multiple books.cats_id columns are not the SQLish way to handle your many-to-many relationship between books and categories. In the parlance of our trade, your books table is denormalized.
What you want is a new table called books_categorys with two columns, book_id and cats_id. It's called a join table. When a row is present in that table, it means a particular book is in a particular category. It's the SQLish way of handling a setup where each book can be in zero or more categorys. Here's an explanation. MySQL join many to many single row
Then you remove all the cats_id columns from books, and retrieve the categories like this.
Then you do something like this SELECT to get the categories.
SELECT books.id, books.name,
categorys.cats_id, categorys.cats_name, categorys.cats_status
FROM books
JOIN books_categorys ON books.book_id = books_categorys.book_id
JOIN categorys ON books_categorys.cats_id = categorys.cats_id
``

How to optimize a query with inner join

My mysql query is too slow and i don't know how to optimize it. My webapp cant load this query because take too much time to run and the webserver have a limit time to get the result.
SELECT rc.trial_id,
rc.created,
rc.date_registration,
rc.agemin_value,
rc.agemin_unit,
rc.agemax_value,
rc.agemax_unit,
rc.exclusion_criteria,
rc.study_design,
rc.expanded_access_program,
rc.number_of_arms,
rc.enrollment_start_actual,
rc.target_sample_size,
(select name from repository_institution where id = rc.primary_sponsor_id) as
primary_sponsor,
(select label from vocabulary_studytype where id = rc.study_type_id) as study_type,
(select label from vocabulary_interventionassigment where id =
rc.intervention_assignment_id) as intervention_assignment,
(select label from vocabulary_studypurpose where id = rc.purpose_id) as study_purpose,
(select label from vocabulary_studymasking where id = rc.masking_id) as study_mask,
(select label from vocabulary_studyallocation where id = rc.allocation_id) as
study_allocation,
(select label from vocabulary_studyphase where id = rc.phase_id) as phase,
(select label from vocabulary_recruitmentstatus where id = rc.recruitment_status_id) as
recruitment_status,
GROUP_CONCAT(vi.label)
FROM
repository_clinicaltrial rc
inner JOIN repository_clinicaltrial_i_code rcic ON rcic.clinicaltrial_id = rc.id JOIN
vocabulary_interventioncode vi ON vi.id = rcic.interventioncode_id
GROUP BY rc.id;
Using inner join instead join could be a solution?
Changing to JOINs vs continuous selects per every row will definitely improve. Also, since you are using MySQL, using the keyword "STRAIGHT_JOIN" tells MySQL to do the query in the order I provided. Since your "rc" table is the primary and all the others are lookups, this will make MySQL use it in that context rather than hoping some other lookup table be the basis of the rest of the joins.
SELECT STRAIGHT_JOIN
rc.trial_id,
rc.created,
rc.date_registration,
rc.agemin_value,
rc.agemin_unit,
rc.agemax_value,
rc.agemax_unit,
rc.exclusion_criteria,
rc.study_design,
rc.expanded_access_program,
rc.number_of_arms,
rc.enrollment_start_actual,
rc.target_sample_size,
ri.name primary_sponsor,
st.label study_type,
via.label intervention_assignment,
vsp.label study_purpose,
vsm.label study_mask,
vsa.label study_allocation,
vsph.label phase,
vrs.label recruitment_status,
GROUP_CONCAT(vi.label)
FROM
repository_clinicaltrial rc
JOIN repository_clinicaltrial_i_code rcic
ON rc.id = rcic.clinicaltrial_id
JOIN vocabulary_interventioncode vi
ON rcic.interventioncode_id = vi.id
JOIN repository_institution ri
on rc.primary_sponsor_id = ri.id
JOIN vocabulary_studytype st
on rc.study_type_id = st.id
JOIN vocabulary_interventionassigment via
on rc.intervention_assignment_id = via.id
JOIN vocabulary_studypurpose vsp
ON rc.purpose_id = vsp.id
JOIN vocabulary_studymasking vsm
ON rc.masking_id = vsm.id
JOIN vocabulary_studyallocation vsa
ON rc.allocation_id = vsa.id
JOIN vocabulary_studyphase vsph
ON rc.phase_id = vsph.id
JOIN vocabulary_recruitmentstatus vrs
ON rc.recruitment_status_id = vrs.id
GROUP BY
rc.id;
One final note. You are using a GROUP BY and applying to the GROUP_CONCAT() which is ok. However, proper group by says you need to group by all non-aggregate columns, which in this case is every other column in the list. You may know this, and the fact the lookups will be the same based on the "rc" associated columns, but its not good practice to do so.
Your joins and subqueries are probably not the problem. Assuming you have correct indexes on the tables, then these are fast. "Correct indexes" means that the id column is the primary key -- a very reasonable assumption.
My guess is that the GROUP BY is the performance issue. So, I would suggest structuring the query with no `GROUP BY:
select . . .
(select group_concat(vi.label)
from repository_clinicaltrial_i_code rcic
vocabulary_interventioncode vi
on vi.id = rcic.interventioncode_id
where rcic.clinicaltrial_id = rc.id
)
from repository_clinicaltrial rc ;
For this, you want indexes on:
repository_clinicaltrial_i_code(clinicaltrial_id, interventioncode_id)
vocabulary_interventioncode(id, label)

Issue in mysql query

I have 2 tables:
table 1:userdetails with fields:uid,mobile,name
table 2:accountdetails with fields:uid,savings,balance
Where uid is common and primary key in both tables.
Now Iam trying to get mobile,savings values from both tables where uid =1 how can we get.I tried below but didnt worked.
select mobile,savings
from userdetails,accountdetails
where userdetails.uid='1'AND
userdetails.uid = accountdetails.uid
Please can some one help
More modern version using the JOIN syntax:
SELECT
a.`mobile`,
b.`savings`
FROM `userdetails` a
JOIN `accountdetails` b
ON a.`uid` = b.`uid`
WHERE a.`uid` = 1
The query should probably look like this:
select ud.mobile, ad.savings
from userdetails ud left join
accountdetails ad
on ud.uid = ad.uid
where ud.uid = 1;
Notes:
Use proper, explicit JOIN syntax.
Use meaningful table aliases and qualify all columns names.
The left join keeps all rows, even if there is no match in the second table. That might be your problem.
I am assuming that uid is actually a number. Don't put numbers around numeric constants.
You could turn on your error display to show you exactly what line is causing the issue.
ini_set('display_errors', 1);
You can try this.
SELECT `ud`.`mobile`, `ad`.`savings`
FROM `userdetails` `ud`
INNER JOIN `accountdetails` `ad` ON `ud`.`uid` = `ad`.`uid`
WHERE `us`.`uid` = 1
Use join
select mobile,savings
from userdetails join accountdetails on userdetails.uid = accountdetails.uid
where userdetails.uid='1'

Help with MySQL Query syntax: ERROR #1066 - Not unique table/alias

I have four tables, user, user_billingprofile, user_shippingprofile, and user_address.
user: userId, dateCreated
user_billingprofile: userId, address
user_shippingprofile: userId, address
user_address: random address crap
Here is the query I have to get a users billing and shipping profiles in one shot.
SELECT * FROM `user`
JOIN `user_billingprofile` ON `user`.`userId` = `user_billingprofile`.`userId`
JOIN `user_address` ON `user_billingprofile`.`currentAddress` = `user_address`.`addressId`
JOIN `user_shippingprofile` ON `user_shippingprofile`.`currentAddress` = `user_address`.`addressId`
JOIN `user_address` ON `user_shippingprofile`.`currentAddress` = `user_address`.`addressId`
I get the error: #1066 - Not unique table/alias: 'user_address'.
Is there a way to take a simple join where a table is accessed twice in the same query, and separate the two results? Preferably with some kind of table prefix...
I'm a bit lost here. I know I could do this in two sepparate queries quite easily, but i'd like to learn how to do stuff like this in one shot.
Any help/suggestions/direction is greatly appreciated, thank you!.
Can you post the structure of your tables? Based on your query I'd say you need to consider changing it up a bit.
That said you can fix your current query by adding a table alias like so:
SELECT * FROM `user`
JOIN `user_billingprofile` ON `user`.`userId` = `user_billingprofile`.`userId`
JOIN `user_address` AS user_billing_address ON `user_billingprofile`.`currentAddress` = `user_address`.`addressId`
JOIN `user_shippingprofile` ON `user_shippingprofile`.`currentAddress` = `user_address`.`addressId`
JOIN `user_address` AS user_shipping_address ON `user_shippingprofile`.`currentAddress` = `user_address`.`addressId`
Note the AS clause I added. You'll probably need to alias the columns too (instead of SELECT * you likely will need SELECT user_shipping_address.address AS user_shipping_address_value, user_billing_address.address AS user_billing_address_value ... )
Hope that helps!

Correct MySQL JOIN format to avoid nested SELECT

I have two separate SELECT statements:
SELECT VCe.VId FROM `VCe` WHERE `YId` = 9007 AND `MaId` =76 AND `MoId` = 2851
SELECT r_pts.p_id FROM r_pts WHERE r_pts.v_id IN (57202, 57203, 69597, 82261, 82260, 69596, 69595, 82259)
When they are run separately they both complete in under .05sec however when I nest the first one within the second, it dramatically increases to 3.3sec.
I would like to do a join so that I can get the output from the second SELECT using the first select as the result set for the IN() but I cannot figure out how to include WHERE conditions in a JOIN.
Edit: Also what is the correct syntax to do a join as I am requesting?
Thanks for your help, its appreciated!
Equivalent to MattMcKnight's query whilst illustrating "how to include WHERE conditions in a JOIN":
SELECT r.p_id
FROM r_pts r
INNER JOIN VCe v
ON v.VId = r.v_id
AND
v.YId = 9007
AND
v.MaId = 76
AND
v.MoId = 2851
SELECT r_pts.p_id FROM r_pts, 'VCe' WHERE r_pts.v_id = VCe.VId AND VCe.YId = 9007 AND VCe.MaId =76 AND VCe.MoId = 2851
The basic goal of a join is to describe how the two tables relate. I inferred from your example that the v_id column in the r_pts table was a foreign key pointing to the VId primary key in the VCe table. When you add a term in the query (such as "r_pts.v_id = VCe.VId") that has a field from each table you wish to join, that tells the database how to match up the rows between the tables to make "virtual rows" that contain the columns from both tables. Your other query terms limit which rows are included in the result set.