MySQL how to query complex relational tables - mysql

I have this tables:
I want to show an article where its subject related term is 'milk'.
subject_catalog table dictionary:
index_key = primary key
subject = takes any words
rt_key = serves as 'related term' foreign key to its own.
sample data for subject_catalog:
|index_key|subject|rt_key|
|------------------------|
| 1 | tea | null |
| 2 | milk | 1 |
|------------------------|
sample data for article:
|article_key|title |pages|
|----------------------------|
| 1 | article_1| 5 |
| 2 | article_2| 3 |
|----------------------------|
sample data for article_subject:
|article_key|index_key|
|---------------------|
| 1 | 1 |
|---------------------|
here is my trial query but it wont show any article:
SELECT
`article`.`title`
FROM
`article_subject`
INNER JOIN `article`
ON (`article_subject`.`article_key` = `article`.`article_key`)
INNER JOIN `subject_catalog`
ON (`article_subject`.`index_key` = `subject_catalog`.`index_key`)
INNER JOIN `subject_catalog` AS `subject_catalog_1`
ON (`subject_catalog_1`.`rt_key` = `subject_catalog`.`index_key`)
WHERE `subject_catalog_1`.`subject` LIKE 'milk%'

Try this
SELECT article.title
FROM article_subject
LEFT JOIN article USING (article_key)
LEFT JOIN subject_catalog USING (index_key)
LEFT JOIN subject_catalog sc2 ON subject_catalog.index_key = sc2.rt_key
WHERE subject_catalog.subject LIKE 'milk%' OR sc2.subject LIKE 'milk%'
http://sqlfiddle.com/#!2/7d5f5/3/0

Select A.title from article A inner Join article_subject S
On A.article_key =S.article_key inner join subject_catalog C
on C.index_key = C.index_key where C.rt_key =1
SQLFIDDLE

Related

Mysql select rows with same id's (3 tables)

I have the following tables:
'blog_content'
'blog_media'
'blog_media_content'
| blog_id | media_id |
========================
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 3 | 4 |
I want to select all blog_media.uri's where blog_media.media_id equals blog_media_content.blog_id.
Please help me to achieve my aim.
An inner join between blog_media and blog_media_content tables would suffice.
SELECT
bm.uri
FROM blog_media bm
INNER JOIN blog_media_content bmc ON bm.media_id = bmc.media_id
WHERE bmc.blog_id =3;
Note:
If you need any additional information from blog table then you need an additional inner join like below:
...INNER JOIN blog_table b ON bmc.blog_id = b.blog_id...
EDIT:
In order to get records for all blog_ids :
SELECT
bm.uri
FROM blog_media bm
INNER JOIN blog_media_content bmc ON bm.media_id = bmc.media_id
ORDER BY bmc.blog_id;

Cannot figure out how to combine two tables using an intermediate id table

I have a journal system that I am currently developing.
There are some tables:
Table 1: issues
issueid | issue_title
1 | November 2016
Table 2: articles
articleid | issueid | article_title
1 | 1 | Yet another article title
Table 3: authors
authorid | firstname | lastname
1 | John | Doe
2 | Jack | Foe
Table 4: articlesauthors
authorarticleid | authorid | articleid
1 | 1 | 1
2 | 2 | 1
The table articlesauthors have the records which author authoring which article.
Now I need to get all the articles with the authors for a specific issue. It should be something like this but cannot figure it out, as I mentioned:
SELECT i.issue_title, ar.article_title, au.firstname, au.lastname
FROM articles ar
INNER JOIN articlesauthors aa1 ON aa1.articleid = ar.articleid
INNER JOIN articlesauthors aa2 ON aa2.articleid = au.authorid
INNER JOIN issues i ON i.issueid = ar.issueid
WHERE i.issueid = 1
Well I am stuck here that I do not know where the type authors table in the query.
Desired output should be like this:
issue_title | article_title | firstname | lastname
November 2... | Yet anothe... | John | Doe
November 2... | Yet anothe... | Jack | Foe
You can also check the modified SQL query :
SELECT ar.article_title, aut.firstname, aut.lastname
FROM issues as issue
INNER JOIN articles as ar ON ar.issueid = issue.issueid
INNER JOIN articlesauthors as aa ON ar.articleid = aa.articleid
INNER JOIN authors as aut ON aut.authorid = aa.authorid
WHERE issue.issueid = 1
This will result in expected output.
according to your posted query, your are using three tables only. you want to get auther firstname and lastname but your are not joining auther table(you are selecting au.firstname ,au.lastname but au id not defined)..try with the below query
select article_title,firstname,lastname from articles
inner join articlesauthors on articlesauthors.articleid=articles.articleid
inner join auther on auther.authorid=articlesauthors.authorid
inner join issue on issue.issueid=articles.issueid
Well thinking a few minutes brought me the solution.
SELECT i.issue_title, ar.article_title, au.firstname, au.lastname
FROM articles ar
INNER JOIN articlesauthors aa ON aa.articleid = ar.articleid
INNER JOIN authors au ON aa.authorid = au.authorid
INNER JOIN issues i ON i.issueid = ar.issueid
WHERE i.issueid = 1
Now this query brings me correct dataset.

MySQL Filtering rows from three tables

Let's say i've got this database:
book
| idBook | name |
|--------|----------|
| 1 |Book#1 |
category
| idCateg| category |
|--------|----------|
| 1 |Adventures|
| 2 |Science F.|
book_categ
| id | idBook | idCateg | DATA |
|--------|--------|----------|--------|
| 1 | 1 | 1 | (null) |
| 2 | 1 | 2 | (null) |
I'm trying to select only the books which are in category 1 AND category 2
This is what I've got so far:
SELECT book.* FROM book,book_categ
WHERE book_categ.idCateg = 1 AND book_categ.idCateg = 2
Obviously, this giving 0 results becouse each row has only one idCateg it does work width OR but the results are not what I need. I've also tried to use a join, but I just can't get the results I expect.
Here it's the SQLFiddle of my current project, the data at the begining is just a sample.
SQLFiddle
Any help will be really appreciated.
You could double join with a constraint on the category id:
SELECT a.* FROM book AS a
INNER JOIN book_categ AS b ON a.idBook = b.idBook AND b.idCateg = 1
INNER JOIN book_categ AS c ON a.idBook = c.idBook AND c.idCateg = 2
You could use a subquery:
SELECT a.* FROM book AS a
WHERE
(SELECT COUNT(DISTINCT idCateg) FROM book_categ AS b
WHERE b.idBook = a.idBook AND b.idCateg IN (1,2)) = 2
If you are on MySQL as your fiddle implies, you should prefer the join variant, since most joins are much faster in MySQL than subqueries.
edit
This one should also work:
SELECT a.* FROM book a
INNER JOIN book_categ AS b ON a.idBook = b.idCateg
WHERE b.idCateg IN (5, 6)
GROUP BY idBook
HAVING COUNT(DISTINCT b.idCateg) = 2
and should be faster than the two above, although you have to change the last number according to the number of category ids you are requesting.

When to use LEFT JOIN and when to use INNER JOIN?

I feel like I was always taught to use LEFT JOINs and I often see them mixed with INNERs to accomplish the same type of query throughout several pieces of code that are supposed to do the same thing on different pages. Here goes:
SELECT ac.reac, pt.pt_name, soc.soc_name, pt.pt_soc_code
FROM
AECounts ac
INNER JOIN 1_low_level_term llt on ac.reac = llt.llt_name
LEFT JOIN 1_pref_term pt ON llt.pt_code = pt.pt_code
LEFT JOIN 1_soc_term soc ON pt.pt_soc_code = soc.soc_code
LIMIT 100,10000
Thats one I am working on:
I see a lot like:
SELECT COUNT(DISTINCT p.`case`) as count
FROM FDA_CaseReports cr
INNER JOIN ae_indi i ON i.isr = cr.isr
LEFT JOIN ae_case_profile p ON cr.isr = p.isr
This seems like the LEFT may as well be INNER is there any catch?
Is there any catch? Yes there is -- left joins are a form of outer join, while inner joins are a form of, well, inner join.
Here's examples that show the difference. We'll start with the base data:
mysql> select * from j1;
+----+------------+
| id | thing |
+----+------------+
| 1 | hi |
| 2 | hello |
| 3 | guten tag |
| 4 | ciao |
| 5 | buongiorno |
+----+------------+
mysql> select * from j2;
+----+-----------+
| id | thing |
+----+-----------+
| 1 | bye |
| 3 | tschau |
| 4 | au revoir |
| 6 | so long |
| 7 | tschuessi |
+----+-----------+
And here we'll see the difference between an inner join and a left join:
mysql> select * from j1 inner join j2 on j1.id = j2.id;
+----+-----------+----+-----------+
| id | thing | id | thing |
+----+-----------+----+-----------+
| 1 | hi | 1 | bye |
| 3 | guten tag | 3 | tschau |
| 4 | ciao | 4 | au revoir |
+----+-----------+----+-----------+
Hmm, 3 rows.
mysql> select * from j1 left join j2 on j1.id = j2.id;
+----+------------+------+-----------+
| id | thing | id | thing |
+----+------------+------+-----------+
| 1 | hi | 1 | bye |
| 2 | hello | NULL | NULL |
| 3 | guten tag | 3 | tschau |
| 4 | ciao | 4 | au revoir |
| 5 | buongiorno | NULL | NULL |
+----+------------+------+-----------+
Wow, 5 rows! What happened?
Outer joins such as left join preserve rows that don't match -- so rows with id 2 and 5 are preserved by the left join query. The remaining columns are filled in with NULL.
In other words, left and inner joins are not interchangeable.
Here's a rough answer, that is sort of how I think about joins. Hoping this will be more helpful than a very precise answer due to the aforementioned math issues... ;-)
Inner joins narrow down the set of rows returns. Outer joins (left or right) don't change number of rows returned, but just "pick up" additional columns if possible.
In your first example, the result will be rows from AECounts that match the conditions specified to the 1_low_level_term table. Then for those rows, it tries to join to 1_pref_term and 1_soc_term. But if there's no match, the rows remain and the joined in columns are null.
An INNER JOIN will only return the rows where there are matching values in both tables, whereas a LEFT JOIN will return ALL the rows from the LEFT table even if there is no matching row in the RIGHT table
A quick example
TableA
ID Value
1 TableA.Value1
2 TableA.Value2
3 TableA.Value3
TableB
ID Value
2 TableB.ValueB
3 TableB.ValueC
An INNER JOIN produces:
SELECT a.ID,a.Value,b.ID,b.Value
FROM TableA a INNER JOIN TableB b ON b.ID = a.ID
a.ID a.Value b.ID b.Value
2 TableA.Value2 2 TableB.ValueB
3 TableA.Value3 3 TableB.ValueC
A LEFT JOIN produces:
SELECT a.ID,a.Value,b.ID,b.Value
FROM TableA a LEFT JOIN TableB b ON b.ID = a.ID
a.ID a.Value b.ID b.Value
1 TableA.Value1 NULL NULL
2 TableA.Value2 2 TableB.ValueB
3 TableA.Value3 3 TableB.ValueC
As you can see, the LEFT JOIN includes the row from TableA where ID = 1 even though there's no matching row in TableB where ID = 1, whereas the INNER JOIN excludes the row specifically because there's no matching row in TableB
HTH
Use an inner join when you want only the results that appear in both tables that matches the Join condition.
Use a left join when you want all the results from Table A, but if Table B has data relevant to some of Table A's records, then you also want to use that data in the same query.
Use a full join when you want all the results from both Tables.
For newbies, because it helped me when I was one: an INNER JOIN is always a subset of a LEFT or RIGHT JOIN, and all of these are always subsets of a FULL JOIN. It helped me understand the basic idea.

help with a sql query - joining two tables

I have two tables like this
Table1 --> route_table
route_id | BusNumber | StartStationID | DestStationID
1 | 90D | 1 | 2
2 | 100A | 1 | 1
Table2 --> station_table
stationId | stationname
1 | Jadcherla
2 | Hyderabad
I want to write a sql query to join the above two tables and generate this table
BusNumber | StartStation | DestStation
90D | Jadcherla | Hyderabad
100A | Jadcherla | Jadcherla
I tried using inner joins but unable to report three columns. I couldn't figure out any keyword to google for this. New to sql, sorry if this is a basic question
Thanks,
Sandeep
SELECT BusNumber,
Start.stationname AS StartStation,
Dest.stationname AS DestStation
FROM route_table
INNER JOIN station_table Start ON Start.stationId = StartStationID
INNER JOIN station_table Dest ON End.stationId = EndStationID
A left join will do it:
SELECT busnumber, d1.stationname, d2.stationname FROM route_table
LEFT JOIN dest d1 ON StartStationID = d1.stationId
LEFT JOIN dest d2 ON StartStationID = d2.stationId
Proved working
SELECT
rt.BusNumber, startStation.stationname, destStation.stationname
FROM rout_table rt
LEFT JOIN station_table startStation ON rt.StartStationID = startStation.stationId
LEFT JOIN station_table destStation ON rt.DestStationID = destStation.stationId