SQL difficult JOIN tables - sql

Suppose I write a query that finds the names of all artists which have members who were not born in the 1960s and another query to find the names of all artists which do not have any members born in the 1960s.
So we are speaking of these three tables:
Artists
ArtistID, ArtistName, Region, EntryDate
Members
MemberId, Firstname, Lastname, Birthday
The relationship between the Aritsts and Members Tables is the XrefArtistsMembers table:
XrefArtistsMembers
MemberId, ArtistID, RespParty
I've started the Query with:
select salesid, firstname, lastname, birthday
from members
where year(birthday) >= 1970 or year(birthday) < 1960;
But what would be true of any artist that appeared in the results of the first query but not in the results of the second?

The question seems not to be looking for code. The question is:
But what would be true of any artist that appeared in the results of the first query but not in the results of the second?
So, the first query gets all artists with SOME members not born in 1960. The second query gets all artists WITH NO member born in 1960. Hence, what you can be sure of is that the artists returned in the first query have SOME BUT NOT ALL members (not) born in 1960.

You can get the list of Artists that have members born outside the 60's with:
SELECT DISTINCT ArtistName
FROM Artists a
JOIN XRefArtistsMembers am ON a.ArtistID = am.ArtistID
JOIN Member m ON m.MemberID = am.MemberID
WHERE YEAR(m.birthday) NOT BETWEEN 1960 and 1969;
To get Artists that have no members born in the 60's:
SELECT DISTINCT ArtistName
FROM Artists a
LEFT JOIN XrefArtistsMembers am ON a.ArtistID = am.ArtistID
LEFT JOIN Member m ON m.MemberID = am.MemberID AND YEAR(m.birthday) BETWEEN 1960 and 1969
WHERE m.MemberID IS NULL

Each can be done with an IN or NOT IN condition:
-- Artists with NO members born in the 60s
SELECT * FROM Artists
WHERE ArtistID NOT IN (
SELECT ArtistID
FROM XrefArtistsMembers x
INNER JOIN Members m ON x.MemberId = m.MemberID
WHERE year(birthday) BETWEEN 1960 AND 1969)
-- Artists with ANY member NOT born in the 60s
SELECT * FROM Artists
WHERE ArtistID IN (
SELECT ArtistID
FROM XrefArtistsMembers x
INNER JOIN Members m ON x.MemberId = m.MemberID
WHERE year(birthday) NOT BETWEEN 1960 AND 1969
)

Related

counting individual elements that meet a certain criteria without duplicates in sqlite3

I'm trying to count all the individual actors from movies in 2004 the problem is when I tried using the count() function it returned how much times every actor appeared in a movie that year.
basically I cant get count() to play well with the GROUP BY function.
SELECT COUNT(name) FROM people
INNER JOIN stars ON stars.person_id = people.id
INNER JOIN movies ON stars.movie_id = movies.id
WHERE movies.year = 2004
GROUP BY name;
relevant tables: movies (id, title, year), stars (movie_id, person_id), people (id, name)
You just need to count the number of DISTINCT person_id in stars (no need to use the people table at all) that have been in movies made in 2004:
SELECT COUNT(DISTINCT person_id) AS num_actors
FROM stars
JOIN movies ON movies.id = stars.movie_id
WHERE movies.year = 2004
Apparently you are not specifying the field you intent to be used for aggregation.Query will return name of actors and respective count of movies. Try below,
SELECT name,COUNT(*) FROM people
INNER JOIN stars ON stars.person_id = people.id
INNER JOIN movies ON stars.movie_id = movies.id
WHERE movies.year = 2004
GROUP BY name;

SQL add attribute from another table

Table WORK
(WORK ID, TITLE, DESCRIPTION, ARTIST ID)
Table ARTIST
(ARTIST ID, FIRSTNAME, LAST NAME, DATE OF BIRTH, DATE OF DEATH)
Hi
My problem is that I have to display the details of all works of art (including the name of the artist who created the work) that are signed.
I managed to go until
Select * from Work WHERE DESCRIPTION LIKE '%Signed%'
and it displays
WorkID TITLE DESCRIPTION ARTISTID
123 1455 Signed 12
However, I must display
WorkID TITLE DESCRIPTION ARTISTID FIRSTNAME LASTNAME
123 1455 Signed 12
How do I do that? I know it has something to do with JOIN but I'm not very sure.
Inner Join will do or can try left join if u need to
SELECT W.*, A.FirstNAme, A.LastName from work w inner join Artist A on
A.Artistid
= W.ArtistId where A.Description LIKE '%Signed%'
Use inner join to get the records that exist in both tables
Select W.WorkID, W.TITLE, W.DESCRIPTION, W.ARTISTID, A.FIRSTNAME, A.LASTNAME
From Work W
Inner Join Artist A on W.WorkID = A.WorkID
Where Description LIKE '%Signed%'
a left outer join would get all the records in the work table and the matching ones in the artist table.
Check this post out to understand joins a bit more : JOINS

sql query to select matching rows for all or nothing criteria

I have a table of cars where each car belongs to a company. In another table I have a list of company locations by city.
I want to select all cars from the cars table whose company has locations on all cities passed into the stored procedure, otherwise exclude those cars all together even if it falls short of one city.
So, I've tried something like:
select id, cartype from cars where companyid in
(
select id from locations where cityid in
(
select id from cities
)
)
This doesn't work as it obviously satisfies the condition if ANY of the cities are in the list, not all of them.
It sounds like a group by count, but can't make it work with what I tried.
I"m using MS SQL 2005
One example:
select id, cartype from cars c
where ( select count(1) from cities where id in (...))
= ( select count(distinct cityid)
from locations
where c.companyid = locations.id and cityid in (...) )
Maybe try counting all the cities, and then select the car if the company has the same number of distinct location cities are there are total cities.
SELECT id, cartype FROM cars
WHERE
--Subquery to find the number of locations belonging to car's company
(SELECT count(distinct cities.id) FROM cities
INNER JOIN locations on locations.cityid = cities.id
WHERE locations.companyId = cars.companyId)
=
--Subquery to find the total number of locations
(SELECT count(distinct cities.id) FROM cities)
I haven't tested this, and it may not be the most efficient query, but I think this might work.
Try this
SELECT e.*
FROM cars e
WHERE NOT EXISTS (
SELECT 1
FROM Cities p
WHERE p.location = e.Location
)

Achieving an SQL Join

I have three tables: Book which holds id, title etc..
member which holds id, name etc...
and loan which holds member_id, book_id, returnDate etc..
I am trying to write a query which gets me back all member details if they have loaned 3 or under three books. So far i have:
SELECT * FROM member m
JOIN member_loans_book mlb ON m.id = mlb.Member_id
HAVING count(mlb.Book_id) <= 3
and it compiles but returns nothing, am i far wrong?
any pointers appreciated.
See sqlFiddle
SELECT m.MemberId, m.Name, COUNT(*)
FROM Member m
JOIN Loan l ON m.MemberId = l.MemberId
GROUP BY m.MemberId, m.Name
HAVING COUNT(*) <= 3

sql get a unique ID then count the number of tuples relating to that ID

Database Structure
MovieInfo (mvID, title, rating, year, length, studio)
DirectorInfo(directorID, firstname, lastname)
MemberInfo(username, email, password)
ActorInfo(actorID, firstname, lastname, gender, birthplace)
CastInfo(mvID*, actorID*)
DirectInfo(mvID*, directorID*)
GenreInfo(mvID*, genre)
RankingInfo(username*, mvID*, score, voteDate)
Query
I need to get the director with the largest number of comedy movies. (I'm also required to use the ALL operator). My understanding is getting the list of mvid where genre = 'Comedy" and directorid:
select mvid
from genreinfo
where genre = 'Comedy'
union all
select directorid
from directorinfo
;
But then how do I count the number of movies a specific director has? And how do I get that single one with the highest count of "comedy" movies?
You're on the right track. I'd recommend looking at JOINs.
I've provided a step-by-step answer on how to obtain the desired results. If you just want the final query, go down to step 5 and pick the one appropriate for your DBMS.
1: Selecting all comedy movie IDs:
SELECT mvid
FROM GenreInfo
WHERE genre = 'Comedy';
2: Selecting the directorIDs of those movies
SELECT directorID
FROM DirectInfo
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy';
3: Selecting the director name of those directors.
SELECT firstname
FROM DirectorInfo
JOIN DirectInfo
ON DirectorInfo.directorID = DirectInfo.directorID
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy';
4: Grouping that query by director to get number of movies:
SELECT firstname, COUNT(*) AS NumberOfMovies
FROM DirectorInfo
JOIN DirectInfo
ON DirectorInfo.directorID = DirectInfo.directorID
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy'
GROUP BY DirectorInfo.directorID;
5: Sort the results and get only the first one:
SELECT firstname, COUNT(*) AS NumberOfMovies
FROM DirectorInfo
JOIN DirectInfo
ON DirectorInfo.directorID = DirectInfo.directorID
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy'
GROUP BY DirectorInfo.directorID
ORDER BY NumberOfMovies
LIMIT 1;
If you're using SQL server, use TOP instead:
SELECT TOP 1 firstname, COUNT(*) AS NumberOfMovies
FROM DirectorInfo
JOIN DirectInfo
ON DirectorInfo.directorID = DirectInfo.directorID
JOIN GenreInfo
ON DirectInfo.mvID = GenreInfo.mvID
WHERE genre = 'Comedy'
GROUP BY DirectorInfo.directorID
ORDER BY NumberOfMovies;
You can use a join and group by to get the result.
select DirectorID,COUNT(mvid)
from DirectInfo d
inner join genreinfo g
ON d.mvid=g.mvid
where genre ='Comedy'
GROUP BY DirectorID
ORDER BY COUNT(mvid)
This is homework? Well, right now you are selecting a list of IDs, some of them representing directors, others representing movies. You notice that this is not at all what you are supposed to do, right?
What you want is a list of directors. So you select from the DirectorInfo table. You also want information about his movies (excatly: the number of movies of a certain kind). So you must join that information from MovieInfo. Now think about what else you need to glue together to get from director to their movies. Then think about how to glue in that genre criterium.
Once you have joined it all together, then you group your results. You want one record per director (instead of ane record per director and movie), so you make a group and count within that group.
I hope this helps you solve your task. Good luck!
select di.directorid, count(1) as 'no_of_comedy_movies'
from DirectorInfo di inner join join DirectInfo dri
on di.directorid = dri.directorid
inner join genreinfo gi
on gi.mvid = dri.mvid
where gi.genre = 'Comedy'
group by dri.directorID
order by no_of_comedy_movies