I asked this last week over the weekend and it got buried in the archives before anyone could answer. So forgive me if you've already seen this.
I teach classes and want to be able to select those students who have taken one class, but not another class. I have two tables: lessons_slots which is the table for every class such as:
--------------------
-ID name slots-
-1 basics 10 -
-2 advanced 10 -
-3 basics 10 -
---------------------
The other table is class_roll, which holds enrollment info, such as:
--------------------
-sID classid firstname lastname-
-1 1 Jo Schmo
-2 1 Person Two
...
-13 2 Jo Schmo
---------------------
What I want to do, I select everyone who has not had the advanced class (for example). I've tried doing
SELECT *
FROM lessons_slots
LEFT JOIN class_roll
ON lessons_slots.ID = class_roll.classid
WHERE lessons_slots.name != 'advanced'
But that doesn't work...All it does is eliminate that row, without eliminating the user. I want Jo Schmo, for example, to not show up in the results. Any ideas?
Not pretty, but works.
SELECT c.*
FROM lessons_slots l
join class_roll c on l.id=c.classid
where concat(firstname,lastname) not in (select concat(firstname,lastname)
from lessons_slots l
join class_roll c on l.id=c.classid where name='advanced')
SELECT * FROM class_roll cl LEFT JOIN lessons_slots ls
ON cl.classid = ls.id AND ls.name != 'advanced'
So you actually want to delete rows? Well then:
DELETE FROM class_roll cl LEFT JOIN lessons_slots ls
ON cl.classid = ls.id AND ls.name != 'advanced'
You could try something to the effect of
SELECT FirstName, LastName FROM class_roll
WHERE NOT EXISTS
(SELECT * FROM class_roll, lesson_slots
WHERE class_roll.classid = lesson_slots.ID
AND lesson_slots.name = 'advanced')
You can then use the result as the basis of a DELETE query.
Related
I'm trying to achieve a query which seems simple but I can't make it work correctly. Here's my database tables structures:
members
-> id
-> last_name
-> first_name
activities
-> id
registrations
-> id
-> member_id
tandems
-> id
-> activitie_id
-> registration_member_one
-> registration_member_two
Here's what i want to achieve:
Mutliple members can register to an activity. Then, i group the registrations by tandems. I want a view with all the tandems listed and there's my problem. When I try a query, it gives me multiple rows, duplicated many times.
Below, an example of the table I want to have:
tandems.id | activities.id | registration_member_one.members.last_name | registration_member_two.members.last_name
1 | 3 | John Doe | Jane Doe
Here's the query I'm working on:
SELECT
tandems.*,
memberOne.id, memberOne.last_name, memberOne.first_name,
memberTwo.id, memberTwo.last_name, memberTwo.first_name,
memberOne_registration.member_id as memberOne,
memberTwo_registration.member_id as memberTwo
FROM tandems
JOIN registrations as memberOne_registration
ON memberOne_registration.member_id = tandems.registration_member_one
JOIN members as memberOne ON memberOne.id = memberOne_registration.member_id
JOIN registrations as memberTwo_registration
ON memberTwo_registration.member_id = tandems.registration_member_two
JOIN members as memberTwo ON memberTwo.id = memberTwo_registration.member_id
WHERE activitie_id = 3;
Any help appreciated!
The error is caused by joining wrong column (member_id) of registrations table with tandems table, instead column registrations.id should be used.
SELECT
tandems.*,
memberOne.id, memberOne.last_name, memberOne.first_name,
memberTwo.id, memberTwo.last_name, memberTwo.first_name,
memberOne_registration.id as memberOne,
memberTwo_registration.id as memberTwo
FROM tandems
JOIN registrations as memberOne_registration ON memberOne_registration.id = tandems.registration_member_one
JOIN members as memberOne ON memberOne.id = memberOne_registration.member_id
JOIN registrations as memberTwo_registration ON memberTwo_registration.id = tandems.registration_member_two
JOIN members as memberTwo ON memberTwo.id = memberTwo_registration.member_id
WHERE activitie_id = 3;
Although other query is virtually the same, I hate working with unnecessarily long alias names so worked with "r1" and "r2" for the two instances of the registration table, and "m1" and "m2" for the members joining context.
SELECT
t.id,
t.activitie_id,
m1.last_name LastName1,
m1.first_name FirstName1,
m2.last_name LastName2,
m2.first_name FirstName2
FROM
tandems t
LEFT join registrations r1
ON t.registration_member_one = r1.id
LEFT JOIN members m1
ON r1.member_id = m1.id
LEFT join registrations r2
ON t.registration_member_two = m2.id
LEFT JOIN members m2
ON r2.member_id = m2.id
WHERE
t.activitie_id = 3;
To help you on this and in the future... Although mentally done, I try to mentally draw out how do I get the pieces together from the first table downstream. This can be seen too by the visual indentation almost like a tree view extension from T to R1 to M1, then R2 to M2 is a different branch. I also prefer to list the left table/alias.column = right table/alias.column in the join condition. How does T get to R1, then how does R1 get to M1.
In this, I used LEFT JOIN to each respective registration and member -- just-in-case only one person registered and a second may be pending. Not sure how your registration is actually structured.
I have a social media like database where users can follow each other, and users can also have interests.
I would like to know how I can return the row(s) that list the users who are following each other and who have at least one interest in common.
I have written the query to display the users who follow each other, and what the user who is being followed is interested in. I need to isolate the pairs of users who follow each other and are interested in the same thing.
CODE SO FAR:
SELECT me.followed, me.following, me.interest FROM
(SELECT followed, following, interest
FROM follow JOIN interest
WHERE followed = interest.user_id
ORDER BY followed) AS me
INNER JOIN follow AS you ON me.following = you.followed
WHERE me.followed = you.following
[table] https://i.imgur.com/t68T4OI.png
A B C
2 1 2
2 1 6
2 1 9
1 2 1
1 2 7
1 2 8
7 15 1
7 15 7
15 7 2
15 7 7
(A = followed, B = following, C = user interest)
Sorry for the formatting, there seems to be no simple way to make tables.
My table so far shows that user 2 follows user 1, and user 1 follows user 2. Same for users 15 and 7. It also shows user 2 is interested in interest 2, interest 6, and interest 9.
I want to write some code that should just return user 7 and user 15, as they are the only users that follow each other and have a common interest (interest 7), but I'm not sure where to start.
I don't knwo if I've misunderstood, but can this query be answered by just the user_follow table?
SELECT * FROM
user_follow a
INNER JOIN
user_follow b
ON
a.followed_user_id = b.following_user_id AND
a.following_user_id = b.followed_user_id AND
a.interest_id = b.interest_id
You need another join to user_interest:
SELECT me.followed_user_id, me.following_user_id,
me.interest_id AS 'same interest id'
FROM user_follow AS me
JOIN user_follow AS you -- me and you follow each other
ON me.following_user_id = you.followed_user_id
AND me.followed_user_id = you.following_user_id
JOIN user_interest AS me_int -- my interest
ON me.following_user_id = me_int.user_id
JOIN user_interest AS you_int -- your interest
ON me.followed_user_id = you_int.user_id
AND me_int.interest_id = you_int.interest_id --must be the same
If I were writing this query, I would want a result set where pairs of users only appear once and there is a count of interests in common.
So:
select uf.followed_user_id, uf.following_user_id,
count(*) as interests_in_common
from user_follow uf join
user_interest uifed
on uifed.user_id = uf.followed_user_id join
user_interest uifing
on uifing.user_id = uf.followed_user_id and
uifing.interest_id = uifed.interest_id
where (uf.followed_user_id, uf.following_user_id) in
(select uf2.following_user_id, uf2.followed_user_id
from user_follow uf2
) and
uf.followed_user_id < uf.following_user_id
group by uf.followed_user_id, uf.following_user_id;
I have this database and i was wondering to create a great select but is too hard for me I guess I tried so many ways and I get really close, but i cant go longer.
Database
Table -> Candidato | IdCandidato(int) | idNome(varchar)
Table -> Voto | idVoto(int) | Candidato_idCandidato(int) | DiaVotacao(date)
i am creating a web voting system and need i greate select to complet my graphics to show the total voting for each day for each candidate.
Candidato = candidate | voto = vote | diaVotacao = voting day (english translation)
I need i response like this:
|VotingDay---------|-----Candidate1----------|-----Candidate2------|--Candidate3
|2014-05-14-------|---13(total votes)---------|------------4------------|-----------10|
|2014-05-15-------|---18(total votes)---------|------------0------------|------------8|
and so far i got this:
|VotingDay---------|-----TOTAL Votes----------|-----Name------|
|2014-05-14-------|---13(total votes)---------|-Candidate1
|2014-05-14-------|---18(total votes)---------|-Candidate2
|2014-05-15-------|---10(total votes)---------|-Candidate1
|2014-05-15-------|----8(total votes)---------|-Candidate2
I used the following code:
SELECT voto.DiaVotacao, IFNULL(COUNT(voto.Candidato_idCandidato),0) as Votos, candidato.Nome
FROM candidato LEFT OUTER JOIN voto ON voto.Candidato_idCandidato=candidato.idCandidato
GROUP BY voto.DiaVotacao, voto.Candidato_idCandidato
Note that i want the count of the votes for each candidate for everey day and if there is no votes apear the number 0 to indicate no votes
did u guys understand?
You need to generate the full list of candidates and days and then do the left outer join. You can get the list of days from the votos table.
Note that when you use count(<column>), it will return 0 if all the values are NULL. There is no need for ifull() or coalesce():
SELECT d.DiaVotacao, COUNT(v.Candidato_idCandidato) as Votos, c.Nome
FROM candidato c cross join
(SELECT DISTINCT v.DiaVotacao FROM voto v
) d LEFT OUTER JOIN
voto v
ON v.Candidato_idCandidato = c.idCandidato and
v.DiaVotacao = d.DiaVotacao
GROUP BY d.DiaVotacao, v.Candidato_idCandidato;
I want to get members and their photos. Every member has 2 photos. (I am not talking about profile image)
There are 2 tables named as Members and MemberPhotos.
Here is my query which doesn't work(expectedly):
SELECT
M.Name as MemberName,
M.LastName as MemberLastName,
(
SELECT
TOP 1
MP.PhotoName
FROM
MemberPhotos MP
WHERE
MP.MemberID = M.ID
AND
MP.IsFirst = 1
) as MemberFirstPhoto,
(
SELECT
TOP 1
MP.PhotoName
FROM
MemberPhotos MP
WHERE
MP.MemberID = M.ID
AND
MP.IsFirst = 0
) as MemberSecondPhoto,
FROM
Members M
Maybe somebody going to say that I should use inner join instead, I don't want to use inner join, if I use it I get data multiple like:
Name Surname PhotoName
Bill Gates bill.png
Bill Gates bill2.png
Steve Jobs steve.jpg
Steve Jobs steve2.jpg
What do you recommend me about query?
Thanks.
EDIT:
Here is the output I want to get:
Name Surname FirstPhoto SecondPhoto
Bill Gates bill.png bill2.png
Steve Jobs steve.jpg steve2.png
The only issue with your example query is that you have an extra comma after
as MemberSecondPhoto
If you remove this it works fine.
SQL Fiddle with demo.
However, while that query is working now, because you know that each member only has two photos, you can use a much simpler query:
SELECT
M.Name as MemberName,
M.LastName as MemberLastName,
MPF.PhotoName as MemberFirstPhoto,
MPS.PhotoName as MemberSecondPhoto
FROM Members M
LEFT JOIN MemberPhotos MPF ON M.ID = MPF.MemberID AND MPF.IsFirst = 1
LEFT JOIN MemberPhotos MPS ON M.ID = MPS.MemberID AND MPS.IsFirst = 0
SQL Fiddle with demo.
(The example that follows is hypothetical, but illustrates the concept).
Using MySQL, say I have 2 tables:
userFromID userToId moreInfo
1 2 cat
1 3 dog
4 1 bear
3 4 fish
And...
userId someInfo addlInfo
1 m 32
2 f 33
3 m 25
4 f 28
And I want to query for a user id, and get back joined info from both tables for all users that share a relationship with user1.
assume that the first table has something like alter table thatFirstTable add unique index(userFromId, userToId) so there won't be any duplicates - each relationship between the two ids will be unique.
it doesn't matter who's the "from" or "to"
so the desired result would be something like this, if queried for relationships with user id: 1
userId moreInfo someInfo addlInfo
2 cat f 33
3 dog m 25
4 bear f 28
Thanks.
/EDIT this "works" but I suspect there's a better way?
SELECT * FROM users JOIN friends ON friends.userFrom = users.id OR friends.userTo = users.id WHERE users.id != 1 AND friends.userFrom = 1 OR friends.userTo = 1
/EDIT2 - I updated the sample output to better reflect the goal
try this query::
select tbl2.userid,tbl1.moreinfo,
tbl2.someinfo,tbl2.addinfo
from tbl1 join tbl2
on (tbl1.usertoid = tbl2.userid and tbl1.userfromid = 1)
You should just join the tables with the query below.
select u.userId, f.moreInfo, u.someInfo, u.addlInfo
from users AS u INNER JOIN friends AS f ON u.userId = f.UserToId
where f.userFrom = 1
Try this. Tested and 100% working
select a.userToID, a.moreInfo, b.someInfo, b.addInfo from tbl1 a
left outer join
tbl2 b on a.userToID = b.userId
where a.userFromID = 1;