How to do an Intersect query in MySQL? - mysql

I have two sql queries and I need the intersect between then. I know mysql does not have the intersect operand, so how could I do it? Tried some solutions I found online but they all return some syntax error. The queries are:
SELECT person_name FROM person NATURAL JOIN (
SELECT * FROM movie NATURAL JOIN role WHERE movie_name = 'Alien'
) alias1
SELECT person_name FROM person WHERE gender = 'f'

You can JOIN all three tables together, and apply both WHERE clauses.
Here is an example. It assumes that your movie table joins to your role table on a column called movie_id, as well as an assumption that you have a person_id column in role and person to join them. You'll need to change this query to use the columns that your tables use.
SELECT
p.person_name
FROM
movie m
INNER JOIN role r
ON (m.movie_id=r.movie_id)
INNER JOIN person p
ON (r.person_id=p.person_id)
WHERE
m.movie_name='Alien'
AND p.gender='f'
Edit: I've used INNER JOIN here, with a guess at the columns to join on, as opposed to keeping the OP's NATURAL JOIN. As the comments to the OP have mentioned, best practice is to explicitly identify the joins, and not rely on a NATURAL JOIN.

Related

Perform an INNER JOIN with more than 2 tables in MySQL

I just recently learned about SQL INNER JOIN and I thought of applying it on a project so basically I have three tables
payers
discounts
items
Now I was just wondering if I can return the results from both of the three tables at once using an INNER JOIN with both of the 3 tables or is it only possible with 2 tables?
If it is possible to use an INNER JOIN with more than 2 tables then kindly please guide me on how to do it and if not then tell me how to do it in any other ways possible.
Now this is the query that I currently have which doesn't work as expected:
SELECT *
FROM payers
INNER JOIN discounts AND items
ON payers.id = discounts.id AND ON payers.id = items.id;
You want two joins. The syntax is:
SELECT *
FROM payers p
INNER JOIN discounts d ON d.id = p.id
INNER JOIN items i ON i.id = p.id
Side notes:
you did not show your actual schema, so this uses the join conditions described in your attempt; you might need to review that
table aliases make the query shorter to write and easier to read
SELECT * is generally not good practice; instead, I would recommend enumerating the columns you want in the SELECT clause, and properly aliasing conflicting columns names, if any (here, all three tables have a column called id, which would cause ambiguity in the resultset)

Joining one table all columns and second table few columns

I have two tables:- PERSON and DATA. What I want to do is fetch all details from PERSON table and only two columns from DATA table only when PERSON.personId = DATA.personId.
I am using this query:-
SELECT *
FROM PERSON AND SELECT DATA.value, DATA.field
FROM DATA where PERSON.personId = DATA.personId;
But I think this is wrong syntax. Can anyone tell me what is the right syntax for it.
SELECT p.*,d.column1,d.column2
FROM Person p
JOIN Data d
ON p.personId = d.personId
WHERE <Condition>
In this query person with all columns and data with your desire column you can fetch by this query.
Something like this:
select
P.*,
D.value,
D.field
from Person P
join Data D on P.PersonID = D.PersonID
change P.* to the specific columns that you need but P.* will get everything from the Person table.
check this post out LEFT JOIN vs. LEFT OUTER JOIN in SQL Server to learn about JOINS, the diagram is good to understand what the different ones do
Its really easy, Just execute this query:
SELECT
PERSON.*,
DATA.value,
DATA.field
FROM
PERSON INNER JOIN DATA USING (`personId`);
It selects all fields of PERSON + value and field from DATA.
Also it uses personId to join the two tables.
Fill free to ask if you need more info.
You can use join (LEFT JOIN)
SELECT * FROM PERSON LEFT JOIN DATA ON PERSON.personId = DATA.personId
Hope it will help you
Here's the correct syntax for achieving what you've asked for:
SELECT PERSON.column1,PERSON.column2,PERSON.columnN,DATA.value
FROM PERSON
INNER JOIN DATA
ON PERSON.personId = DATA.personId
Line#1: lists the columns that you want to select with references to their parent tables.
Line#2 and 3: are the two tables that you want to select from and join with
Line#4: is the join condition between the two tables (with matching IDs or other information)

Multiple joins on the same table with counting in one query

I have an elementary question about SQL query with joining the same table twice. It sounds very simple, but I have some troubles with it. I hope, anyone can help me with this issue :)
I have two little tables: "peoples" (columns: id, name, ...) and "likes" (id, who, whom). People may set the "likes" to each other. The relationship is many to many.
I want get the table with peoples likes: count of received "likes", delivered and count of mutual likes.
All is correctly, when I use only one join. But for two joins (or more) MySQL combine all rows (as expected) and I get wrong values in counts. I don't know, how I must use count/sum/group-by operators in this case:( I would like to do this without subqueries in one query.
I used a query like this:
SELECT *, count(l1.whom), count(l2.whom)
FROM people p
LEFT JOIN likes l1 ON l1.who = p.id
LEFT JOIN likes l2 ON l2.whom = p.id
GROUP BY p.id;
SELECT p.id, name,
count(lwho.who) delivered_likes,
count(lwhom.whom) received_likes,
count(lmut.who) mutual_likes
FROM people AS p
LEFT JOIN likes AS lwho ON p.id = lwho.who
LEFT JOIN likes AS lwhom ON lwhom.id = lwho.id
LEFT JOIN likes AS lmut ON lwhom.who = lmut.whom AND lwhom.whom = lmut.who
GROUP BY p.id;
But it's calculated the counts of likes incorrect.
It's issue just for training and performance is not important, but I guess, that three joins in my last query is too much. Can I do it using 2 joins?
Thanks in advance for help.
I surmise that there is a 1:N relationship between people and likes.
One problem with your second query, as far as I can tell, is that the lwhom correlation of likes is joined to lwho via id=id. Basically lwhom is lwho. I'd recommend changing the ON clause for this correlation from lwhom.id = lwho.id to p.id = lwhom.whom.
The counts will still be affected by the JOINs, however. Supposing that you have an ID column in the likes table, though, you could then have each COUNT tally the distinct Like IDs per person – if not, consider just using COUNT(DISTINCT correlation.*) instead.
Digressions aside, the following should hopefully work:
SELECT p.id, name,
count(distinct lwho.id) delivered_likes,
count(distinct lwhom.id) received_likes,
count(distinct lmut.id) mutual_likes
FROM people AS p
LEFT JOIN likes AS lwho ON p.id = lwho.who
LEFT JOIN likes AS lwhom ON p.id = lwhom.whom
LEFT JOIN likes AS lmut ON lwhom.who = lmut.whom AND lwhom.whom = lmut.who
GROUP BY p.id,p.name;
I have an SQL Fiddle here.

how the inner join can be nested?

I am newbie in SQL and practicing queries for my university assignments...I have three tables in the database:
1. student:
studentid pk
fname
school
2. books:
bookid pk
bookname
3. issue:
issueid pk
studentid fk
bookid fk
fine
and I am trying to solve this query:
select the bookname and the average fine for those students who have issued two or more books.
I have tried using nested INNER JOINs as:
SELECT fname,bookname,AVG(fine) FROM
student INNER JOIN ( books INNER JOIN issue ON books.bookid=issue.bookid) ON
student.studentid=issue.issueid
GROUP BY fname
HAVING COUNT(bookid)>1;
but failed.Is there any mistake or is it totally wrong to nest JOINs as above? Or please hint me if there is an another way to do this using JOIN.
You can do two separate joins:
SELECT fname,bookname,AVG(fine)
FROM student
INNER JOIN issue ON student.studentid=issue.issueid
INNER JOIN books ON books.bookid=issue.bookid
GROUP BY fname
HAVING COUNT(bookid)>1;
Another possibility is to join on several tables in the same INNER JOIN:
SELECT fname,bookname,AVG(fine)
FROM student
INNER JOIN (issue, books) ON (student.studentid=issue.issueid AND books.bookid=issue.bookid)
GROUP BY fname
HAVING COUNT(bookid)>1;
The reason your query was wrong is simply that you did not use the right syntax...: there is no such thing as nested joins.
This page is the MySQL documentation page for joins. You will find many examples of how to handle joins.
This one should work. You can append INNER JOINs after each other, and use the values of any previously called tables after the ON parameter.
SELECT student.fname, books.bookname, AVG(issue.fine)
FROM student
INNER JOIN issue ON issue.studentid = student.studentid
INNER JOIN books ON books.bookid = issue.bookid
GROUP BY student.fname
HAVING COUNT(books.bookid)>1

SQL Inner join with count

I have two tables one called games and one called reviews.
I am trying to join these two tables together and have looked through the documentations and also the other questions here on stackoverflow.
SELECT games.id, games.title, games.developer, reviews.review, reviews.review_title,
(SELECT review, COUNT(*)
FROM reviews
GROUP BY review) AS Numberofreviews
FROM games
INNER JOIN reviews
ON games.ean=reviews.games_ean;
The query that i am trying to make is to get a table that shows the list of games and how many reviews each game has recieved.
But when i try implementing the above code i get the error operand should contain one column
Ive looked at other people getting this error but not in the same situation.
Any help would be apprecatied
edit: this is with mySQL
You need to use the correlated subquery and for the error it clearly says there should be one column from your subquery
SELECT
g.id,
g.title,
g.developer,
(SELECT
COUNT(*)
FROM
reviews
WHERE games_ean = g.ean) AS Numberofreviews
FROM
games g
INNER JOIN reviews r
ON g.ean = r.games_ean ;
You get the error "operand should contain one column" because your subquery returns two columns. Only one is allowed in this situation. However you don't need a subquery at all. Make a left join (in case for no reviews) and aggregate the reviews:
SELECT games.*, COUNT(reviews.games_ean)
FROM games
LEFT JOIN reviews ON reviews.games_ean = games.ean
GROUP BY games.ean;
I assume that games.* is functional depended on games.ean (i.e. games.ean is unique).
As this statement seems to cause confusion I want to emphasize that a projection on non aggregated attributes in a grouped statement is only defined for attributes which are functionally depended on the the grouped attributes. The statement (given the assumption that games.ean is unique) therefore is valid and makes perfect sense!
MySQL allows projections of non aggregated attributes which are not functionally depended! However they are not defined in ANSI-SQL nor are they deterministic as MySQL selects one undefined value for each non aggregated attribute.
You should move the subquery into the from clause, instead of reviews to get the number:
SELECT g.id, g.title, g.developer, r.Numberofreviews
FROM games g inner join
(SELECT games_ean, COUNT(*) as Numberofreviews
FROM reviews
GROUP BY games_ean
) r
on g.ean = r.games_ean;
It does not make sense to have a column called review_title, because there might be more than one review.
The query that i am trying to make is to get a table that shows the list of games and how many reviews each game has recieved.
SELECT games.id, games.title, games.developer, COUNT(DISTINCT reviews.*) as reviews_amount
FROM games
LEFT JOIN reviews ON games.ean = reviews.games_ean
GROUP BY games.ean;