SQL in vs intersection - sql

I want to select results from a table
USER HOBBY
John Sport
Ann Piano
Lee Reading
Ann Sport
Lee Piano
And I want to search people who have more than one common hobbies. Which query has better performance,
select user from table where hobby = "sport"
intersect
select user from table where hobby = "piano"
Or
select user from table where user in (select user from table where hobby = "piano") and where hobby = "sport"?

best performance is from
select user from table where hobby = "sport" or hobby = "piano"
but if this is just a teorical excample, then many test have been made, here some:
http://www.execsql.com/post/intersectexcept-versus-innot-in
BTW there isn't a better solution than try out by yourself the execution time of the query

In Oracle, assuming (USER, HOBBY) is unique, you could use a GROUP BY query:
SELECT user
FROM user_hobby
WHERE hobby IN ('piano', 'sport')
GROUP BY user
HAVING COUNT(*) = 2
This will make Oracle perform at most a single pass on data whereas the INTERSECT would treat each query separately and would therefore need two passes.

Related

Multiple JOIN, with one table needed two times

i am trying to make up this situation in my app: there are users who can select the languages they speak (such as english, spanish, japanese and so on) and users who can confirm the languages selected by others users (like in LinkedIn, where you can confirm the skill of another person).
I have 4 tables in a DBRM: Users, Languages, Users_Language and Users_Confirmations.
The bodies:
Users
id name lastname ...
Languages
id name
Users_Languages
user_id language_id
Users_Confirmations
user_id language_id other_id ------> here other_id refers to Users table, like user_id. They both refer to Users table, since an user can confirm another user
For example:
John Smith speaks English, Spanish and Danish.
Luke Red and Jennifer Brown confirmed English on John Smith.
Now, I want to get all Users who, for example, have confirmed the user with id "4", and show them in a HTML list. And I would want to get it with both PURE SQL and Laravel (Eloquent or Query Builder).
Thank you in advance!
Here you have to change your table attributes to avoid repetition, use just
Users_Languages_ID as a foreign key to refer to the Users_Langages table
-- Users_Confirmations
confirmation_id user_language_id
You can just use Users_Confirmations, and for each confirmation added, you will insert a row that contains user_language_id
Returning to the question(to get users who confirmed the user with id "4")
SELECT Users.name, Users.lastname, Languages.name
FROM Users_Confirmations
JOIN Users_Languages ON Users_Languages.id = Users_Confirmations.user_language_id
JOIN Languages ON Languages.id = Users_Languages.language_id
JOIN Users ON Users.id = Users_Languages.user_id
WHERE Users_Languages.user_id = 4

SQL add columns of each record together

To be blunt I don't know SQL however I don't want the answer, I want to work it out myself.
Here's the question:
Write a SQL query to calculate the number of goals for each team.
players
id name team_id goals
1 Joel 1 3
2 Ed 2 1
3 Simon 2 4
teams
id name
1 New Zealand
2 London
What I'm asking for is an arrow to information that will allow me to solve the question.
I've tried looking myself but I don't even know the correct terminology to ask the question, googling 'write sql to add fields for each row' just seems to return about adding columns or inserting.
You need to first try to JOIN your tables(id in Teams will be linked to TeamId in Players.) based on the foreign key columns.
Then you need to do the GROUP BY and use the aggregate function SUM to get the goals for each team.
So your query will be like:
select t.name, sum(p.goals) as cnt,
from players p inner join teams t on p.teamid = t.id
group by t.name
First you have to group players by teams : use t1.id=t2.id to join values in the tables, and then group theme by "BROUP BY" t.name.
Then : user "SUM(value)" function who sum values .
select teams.name,sum(players.goals) from players,team where player.team_id=teams.id group by teams.name;

Select query from three tables SQL

The database is Oracle XE .
Let me explain the scenario first ,
Two tables Movie and UserInfo are in a relationship many to many using the junction table Rating.
Rating ( MovieID (FK) , UserName(FK) , Rating)
MovieID and UserName are both respectively the primary keys in the respected tables.
What I am trying to do is make a select statement to select the MovieNames from the Movie table where UserName is not equal to the given input. As the MoveID was the FK, but I need to retrieve MovieName if the movie is not already been rated by the GIVEN user, so I guess I may need to make a rather complex joining operation - which I can't figure out or maybe joining two or more different query using where.
Thanks in advance and please if possible give an explanation about the solution.
This seems like a classic usecase for the not exists operator:
SELECT *
FROM movie m
WHERE NOT EXISTS (SELECT *
FROM rating r
WHERE r.movideid = m.moveid AND
r.username = 'given username here')

SQL: How do I find which movie genre a user watched the most? (IMDb personal project)

I'm currently working on a personal project and I could use a little help. Here's the scenario:
I'm creating a database (MS Access) for all of the movies myself and some friends have ever watched. We rated all of our movies on IMDb and used the export feature to get all of the movie data and our movie ratings. I plan on doing some summary analysis on Excel. One thing I am interested in is the most common movie genre that each person watched. Below is my current scenario. Note that the column "const" is the movies' unique IDs. I also have individual tables for each person's ratings and the following tables are the summary tables that make up the combination of all the movies we have watched.
Here's the table I had: http://imgur.com/v5x9Dhg
I assigned each genre an ID, like this: http://imgur.com/aXdr9XI
And here is a table where I have separate instances for each movie ID and a unique genre: http://imgur.com/N0wULo8
I want to find a way to count up all of the genres that each person watches. Any advice? I would love to provide any additional information that you need!
Thank you!
You need to have at least one table which has one row per user and const (movie watched). In the 3 example tables you posted nothing shows who watched which movies, which is information you need to solve your problem. You mention having "individual tables for each person's ratings," so I assume you have that information. You will want to combine all of them though, into a table called PERSON_MOVIE or something of the like.
So let's say your second table is called GENRE and its columns are ID, Genre.
Let's say your third table is called GENRE_MOVIE and its columns are Const and ID (ID corresponds to ID on the GENRE table)
Let's say the fourth table, which you did not post, but which is required, is called PERSON_MOVIE and its columns are person, Const, rating.
You could then write a query like this:
select vw1.*, ge.genre
from (select um.person, gm.id as genre_id, count(*) as num_of_genre
from user_movie um
inner join genre_movie gm
on um.const = gm.const
group by um.person, gm.id) vw1
inner join (select person, max(num_of_genre) as high_count
from (select um.person, gm.id, count(*) as num_of_genre
from user_movie um
inner join genre_movie gm
on um.const = gm.const
group by um.person, gm.id) x
group by person) vw2
on vw1.person = vw2.person
and vw1.num_of_genre = vw2.high_count
inner join genre ge
on vw1.genre_id = ge.id
Edit re: your comment:
So right now you have multiple tables reflecting people's ratings of movies. You need to combine those into a table called PERSON_MOVIE or something similar (as in example above).
There will be 3 columns on the table: person, const, rating
I'm not sure if access supports the traditional create table as select query but ordinarily you would be able to construct such a table in the following way:
create table person_movie as
select 'Bob', const, [You rated]
from ratings_by_bob
union all
select 'Sally', const, [You rated]
from ratings_by_sally
union all
select 'Jack', const, [You rated]
from ratings_by_jack
....
If not, just combine the tables manually and add a third column as shown indicating what users are reflected by each row. Then you can run my initial query.

SQL Database SELECT question

Need some help with an homework assignment on SQL
Problem
Find out who (first name and last name) has played the most games in the chess tournament with an ID = 41
Background information
I got a table called Games, which contains information...
game ID
tournament ID
start_time
end_time
white_pieces_player_id
black_pieces_player_id
white_result
black_result
...about all the separate chess games that have taken place in three different tournaments ....
(tournaments having ID's of 41,42 and 47)
...and the first and last names of the players are stored in a table called People....
person ID (same ID which comes up in the table 'Games' as white_pieces_player_id and
black_pieces_player_id)
first_name
last_name
...how to make a SELECT statement in SQL that would give me the answer?
sounds like you need to limit by tournamentID in your where clause, join with the people table on white_pieces_player_id and black_pieces_player_id, and use the max function on the count of white_result = win union black_result = win.
interesting problem.
what do you have so far?
hmm... responding to your comment
SELECT isik.eesnimi
FROM partii JOIN isik ON partii.valge=isik.id
WHERE turniir='41'
group by isik.eesnimi
having count(*)>4
consider using the max() function instead of the having count(*)> number
you can add the last name to the select clause if you also add it to the group by clause
sry, I only speak American. What language is this code in?
I would aggregate a join to that table to a derived table like this:
SELECT a.last_name, a.first_name, CNT(b.gamecount) totalcount
FROM players a
JOIN (select cnt(*) gamecount, a.playerid
FROM games
WHERE a.tournamentid = 47
AND (white_player_id = a.playerid OR black_player_id = a.playerid)
GROUP BY playerid
) b
ON b.playerid = a.playerid
GROUP BY last_name, first_name
ORDER BY totalcount
something like this so that you are getting both counts for their black/white play and then joining and aggregating on that.
Then, if you only want the top one, just select the TOP 1