MYSQL Relational Query Issue - mysql

I'm working with the following DB model
A client has asked me to make a few changes to their DB, I haven't played with relational databases in a few years, generally work with flat DB's
Could someone help me on my way with giving me an example of how the following query would work.
say if I wanted to
select all films with a title like '%Matrix%' under a certain genreID
Any assistance would be greatly appreciated

Use an inner join to join the three tables
SELECT F.title
FROM film F
INNER JOIN filmgenres FG
ON F.filmid = FG.film_filmid
INNER JOIN genres G
ON FG.genres_genreid = G.genreid
WHERE F.title LIKE '%Matrix%' AND G.genre = "Some Genre"

You need to join the tables first,
SELECT a.*, c.Genre
FROM Film a
INNER JOIN FilmGenres b
ON a.FilmID = b.Film_FilmID
INNER JOIN Genres c
ON b.Genre_GenreID
WHERE a.Title LIKE '%matrix%'
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
but if you want to search for a specific genre, then you might add a condition as well,
SELECT a.*, c.Genre
FROM Film a
INNER JOIN FilmGenres b
ON a.FilmID = b.Film_FilmID
INNER JOIN Genres c
ON b.Genre_GenreID
WHERE a.Title LIKE '%matrix%' AND c.GenreID = 10

SELECT Film.*
FROM Film f
JOIN FilmGenres fg ON g.Film_FilmID = f.FilmID
WHERE fg.Genres_GenreID = 3
AND Title LIKE '%Matrix%'

SELECT * FROM Film INNER JOIN FilmGenres ON Film.FilmID = FilmGenres.Film_FilmID
WHERE FilmGenres.Genres_GenreID = 1
AND
Film.Title like '%Matrix%'

It's a pretty simple join:
select
Film.*
from
Film
inner join FilmGenres on
Film.FilmID = FilmGenres.Film_FilmID
where
Film.Title like "%Matrix%" and
FilmGenres.Genres_GenreID = ?

Related

Sql count number of tested models by car brands

I have 3 tables the first one is tests which contains tested brand_id and model_id and brands which
contains car brands and lastly models which contains brand_id.
I want to show all brands and models and number of tests for respective model. If no tests than it should be zero.
This is what I achieved so far;
select
b.id,
b.brand_name,
m.model_name,
(select sum(coalesce(count(m.id), 0)) from test where test.brand_id = b.id and test.model_id = m.id) model_count
from
brands b
left join models m on
m.brand_id = b.id
left join test t on
t.brand_id = b.id
group by
b.brand_name,
m.model_name
Thanks for any help
You can use group by as follows:
select
b.id,
b.brand_name,
m.model_name,
count(t.brand_id) model_count
from brands b join models m on m.brand_id = b.id
left join test t on t.brand_id = b.id and t.model_id = m.id
group by b.id, b.brand_name, m.model_name
A correlated subquery is a perfectly reasonable way to solve this problem. But . . . you don't don't test in the outer query and the subquery can be much simplified:
select b.id, b.brand_name, m.model_name,
(select count(*)
from test t
where t.brand_id = b.id and t.model_id = m.id
) as model_count
from brands b left join
models m
on m.brand_id = b.id;
Under many circumstances, this will have better performance than the equivalent aggregation query because it avoids aggregation over the entire data set.

MySQL: LIKE Wildcard inside WHERE clause

I SELECT data from a MySQL database and I'm trying to replace WHERE column_name = 'name' with a wildcard like WHERE column_name LIKE '%name%'.
Sounds too easy, right?
The original code (which works perfectly) looks like this:
SELECT DISTINCT a.title_id, a.artist_id, fe_title.title, fe_artist.artist
FROM fe_title_artist AS a
INNER JOIN fe_title ON a.title_id = fe_title.id
INNER JOIN fe_artist ON a.artist_id = fe_artist.id
INNER JOIN fe_title_artist AS b
WHERE a.title_id=b.title_id
and b.artist_id=(SELECT id FROM fe_artist WHERE artist = 'Patrick Duffy')
What I tried and failed with looks like this:
SELECT DISTINCT a.title_id, a.artist_id, fe_title.title, fe_artist.artist
FROM fe_title_artist AS a
INNER JOIN fe_title ON a.title_id = fe_title.id
INNER JOIN fe_artist ON a.artist_id = fe_artist.id
INNER JOIN fe_title_artist AS b
WHERE a.title_id=b.title_id
and b.artist_id=(SELECT id FROM fe_artist WHERE artist LIKE '%Patrick%')
No results on this one.
Is a wildcard within a where clause just too much? Is the self join causing the problem? Is there a way to code this differently? Am I just stupid?
I hope someone can help me. Thank you.
Its due to Subquery returns more than 1 rows. Please use below Query.
SELECT DISTINCT a.title_id, a.artist_id, fe_title.title, fe_artist.artist
FROM fe_title_artist AS a
INNER JOIN fe_title ON a.title_id = fe_title.id
INNER JOIN fe_artist ON a.artist_id = fe_artist.id
INNER JOIN fe_title_artist AS b
WHERE a.title_id=b.title_id
and b.artist_id IN (SELECT id FROM fe_artist WHERE artist LIKE '%Patrick%')

MySQL: how to combine three tables

I have a table with persons (personid,name), another table with camps (campid,title) and a third table with camp participations (id,personid,campid).
Now, for a given camp, I need a list of all other camp participations by all persons participating in the current camp.
But I have no idea how to join these tables. I have looked at a lot of other examples, but I can't really seem to get any inspiration from those...
This should work:
SELECT *
FROM PERSONS AS D INNER JOIN CAMP_PARTICIPATIONS AS E ON D.PERSONID = E.PERSONID
INNER JOIN CAMPS AS F ON F.CAMPID = E.CAMPID
WHERE F.CAMPID <> [your_camp] AND A.PERSONID IN (
SELECT A.PERSONID
FROM PERSONS AS A INNER JOIN CAMP_PARTICIPATIONS AS B ON A.PERSONID = B.PERSONID
INNER JOIN CAMPS AS C ON C.CAMPID = B.CAMPID
WHERE C.CAMPID = [your_camp] )
select persons.*,participations.*,camps.* from persons left join participations
on participations.personid=persons.personid
left join camps on camps.campid=participations.campid
where camp.campid=1;
now u can change the campid in where clause and place column name which u want in select clause

Count matched words from IN operator

i have this little mysql query :
select t.title FROM title t
inner join movie_keyword mk on mk.movie_id = t.id
inner join keyword k on k.id = mk.keyword_id
where k.keyword IN (
select k.keyword
FROM title t
inner join movie_keyword mk on mk.movie_id = t.id
inner join keyword k on k.id = mk.keyword_id
where t.id = 166282
)
LIMIT 15
as you can see it will return all titles from title that have at least one the same keyword that have movie with id 166282.
Now i have problem, because i want also count how many keywords was matched in IN operator(let's say i want to see only titles that have 3 or more the same keywords), i tried something with aggregate functions, but everything failed, so i came here with my problem. Maybe somebody can give me some advice, or code example.
I'm not also sure, if this "subquery way" is good, so if there are some better options how i should solve my problem, I am open to any suggestions or tips.
Thank you!
#Edit
So after some problems, i have one more. This is my current query :
SELECT s.title,s.vote,s.rating,count(dk.key) as keywordCnt, count(dg.name) as genreCnt
FROM series s
INNER JOIN series_has_genre shg ON shg.series_id = s.id
INNER JOIN dict_genre dg ON dg.id = shg.dict_genre_id
INNER JOIN series_has_keyword shk ON shk.series_id = s.id
INNER JOIN dict_keyword dk ON dk.id = shk.dict_keyword_id
WHERE dk.key IN (
SELECT dki.key FROM series si
INNER JOIN series_has_keyword shki ON shki.series_id = si.id
INNER JOIN dict_keyword dki ON dki.id = shki.dict_keyword_id
WHERE si.title LIKE 'The Wire'
)
and dg.name IN (
SELECT dgo.name FROM series so
INNER JOIN series_has_genre shgo ON shgo.series_id = so.id
INNER JOIN dict_genre dgo ON dgo.id = shgo.dict_genre_id
WHERE so.title LIKE 'The Wire'
)
and s.production_year > 2000
GROUP BY s.title
ORDER BY s.vote DESC, keywordCnt DESC ,s.rating DESC, genreCnt DESC
LIMIT 5
Problem is, it is very, very, very slow. Any tips what i should change, to run it faster ?
Will this work for you:
select t.title, count(k.keyword) as keywordCount FROM title t
inner join movie_keyword mk on mk.movie_id = t.id
inner join keyword k on k.id = mk.keyword_id
where k.keyword IN (
select ki.keyword
FROM title ti
inner join movie_keyword mki on mki.movie_id = ti.id
inner join keyword ki on ki.id = mki.keyword_id
where ti.id = 166282
) group by t.title
LIMIT 15
Note that I have changed the table names inside the nested query to avoid confusion.

#1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

Hi so I'm attempting to get all books in a series that a customer hasn't ordered yet. My current theory is that the best way to do this was to find what book series they have ordered. then build a list of all the books in those series and then find all the books in that list that they haven't ordered. However in my attempts to word a messy triple query I get the above error after only getting to the second part. Here's my query so far:
SELECT books.bookid
FROM books, bookseries, series
WHERE books.bookID=bookseries.bookID
AND bookseries.bookID=series.seriesID
series.seriesID IN (SELECT series.seriesID, COUNT(series.seriesID) as cnt
FROM customers, orders, orderlines, books, bookseries, series
WHERE customers.custID=1
AND customers.custID=orders.custID
AND orders.orderID=orderlines.orderID
AND orderlines.bookID=books.bookID
AND books.bookID=bookseries.bookID
AND bookseries.seriesID=series.seriesID
GROUP BY series.seriesID
ORDER BY cnt desc LIMIT 1)
I know for a fact that inside query works; only it returns two columns, seriesID and cnt and I think that might be my problem but I'm not sure. I also saw that a lot of people have had this issue and joins usually work but I don't quite know enough about them. Can someone help/teach me? Perhaps suggest a better way? Speed isn't too important, this is to test some things out on a fun project I'm working on. Thank you very much!
Ok let me know if I'm doing this wrong but: http://sqlfiddle.com/#!2/6816c/1 is what the database looks like. I'm trying to get an output of book titles that are in the same series that I know a customer likes and that they don't own. So for user 1 I know they have harry potter 1, 2, 6, 7. So my query will find that they like the harry potter series and output the titles they don' t own which in this case is Harry Potter 3, 4, 5. Or Azkaban, Goblet of Fire and order of the phoenix.
In summary: Step one: find all the series that customer has books from. Step two: Find all the books from all those series. Step three: find the books in that list that the customer doesn't own.
SELECT b.bookID, b.title
FROM books AS b
INNER JOIN bookseries AS bs ON bs.bookID = b.bookID AND bs.seriesID IN (
SELECT series.seriesID
FROM customers, orders, orderlines, books, bookseries, series
WHERE customers.custID=1
AND customers.custID=orders.custID
AND orders.orderID=orderlines.orderID
AND orderlines.bookID=books.bookID
AND books.bookID=bookseries.bookID
AND bookseries.seriesID=series.seriesID
GROUP BY series.seriesID)
WHERE b.bookID NOT IN (
SELECT ol.bookID
FROM orders AS o
INNER JOIN orderlines AS ol ON ol.orderID = o.orderID
INNER JOIN books AS b ON b.bookID = ol.bookID
WHERE o.custID = 1
)
Okay the format is a little weird but this is my final query. Big thanks to #hex494D49 for getting me on the right track!
Fetching books of the series (1) that aren't yet ordered by customer (1)
SELECT b.bookID, b.title
FROM books AS b
INNER JOIN bookseries AS bs ON bs.bookID = b.bookID AND bs.seriesID = 1
WHERE b.bookID NOT IN (
SELECT ol.bookID
FROM orders AS o
INNER JOIN orderlines AS ol ON ol.orderID = o.orderID
INNER JOIN books AS b ON b.bookID = ol.bookID
WHERE o.custID = 1
)
Or
SELECT b.bookID, b.title
FROM books AS b
INNER JOIN bookseries AS bs ON bs.bookID = b.bookID AND bs.seriesID = 1
LEFT JOIN orderlines AS ol ON ol.bookID = b.bookID
LEFT JOIN orders AS o ON o.orderID = ol.orderID AND o.custID = 1
WHERE ol.bookID IS NULL
Usage in PHP:
$rs = mysqli_query("SELECT b.bookID, b.title
FROM books AS b
INNER JOIN bookseries AS bs ON bs.bookID = b.bookID AND bs.seriesID = " . $_GET["seriesID"] . "
WHERE b.bookID NOT IN (
SELECT ol.bookID
FROM orders AS o
INNER JOIN orderlines AS ol ON ol.orderID = o.orderID
INNER JOIN books AS b ON b.bookID = ol.bookID
WHERE o.custID = " . $_GET["custID"] . "
)");
while($b = mysqli_fetch_array($rs, MYSQLI_ASSOC)){
echo $b["bookID"] . " - " . $b["title"] . "<br />";
}