tags:

views:

202

answers:

6

Hi,

I'm trying to write an SQL query for my program, but I just can't figure out how. I don't know enough SQL.

I'm trying to implement an online team system (for some website). I have two tables:

teams | teamId, eventId
teammembers | teamId, userId, status

Now, I need to: "delete all records in teammembers where the eventId for the corresponding teamId is 1.

I'm trying:

delete from teammembers where teamId=teams.teamId and teams.eventId=1;

I'm not sure if this is really doing what I'm trying to do.

Please tell me if my query is wrong, and if it is (which probably is), please teach me how to write such a query.

Thanks!

+1  A: 
delete from teammembers where teamid in 
(
  select teamid from teams where eventid = 1
)

Assuming that teamid is the joining column.

davek
why use a non-scalable where IN instead of a join?
hobodave
thanks for the quick response :)
Here Be Wolves
a join should be faster (and better solution IMHO)
Hogan
@hobodave: yes, that would be an issue for mysql, but not necessarily for other DBs (depending on the metrics etc.)
davek
@davek: this performs worse on mssql too.
Hogan
+12  A: 

You don't specify your RDBMS so here it is in MySQL

DELETE teammembers FROM teammembers
JOIN teams on teammembers.teamId = teams.teamId
WHERE teams.eventId = 1
hobodave
+1 for not using unneeded subselects. However dont you need to speify you only want to delete the `teammembers` records and not the `teams` records as well when you do a join in a delete statement?
prodigitalson
You are correct, I fixed it.
hobodave
and can you explain why this query is more efficient than using subselects? or point me to a link that does that? I don't want to have ask stuff on SO each time I face a tough query situation :)
Here Be Wolves
and yes, it is mysql. and I forgot to say thanks!
Here Be Wolves
with the sub-query it has to store all the results of the sub-query before it can perform / finish the outer part. This takes more resources. Also, all sql systems are very good at doing joins so they often work better because the engine was designed to do them fast.
Hogan
@jrharshath: MySQL is notoriously terrible at subquery optimization. In many cases, for every row of the outer query, it executes the inner query.
hobodave
@jrharshath: see http://dev.mysql.com/doc/refman/5.1/en/rewriting-subqueries.html
hobodave
Also: http://www.xaprb.com/blog/2006/04/30/how-to-optimize-subqueries-and-joins-in-mysql/ I suggest googling for mysql and subquery.
hobodave
@hobodave: it would not do it for every row using in as part of the where clause.
Hogan
@Hogan: I prefaced my statement with "In many cases".
hobodave
thanks for all the help people :)
Here Be Wolves
@hobodave: too true, can't count the number of times I've seen it written by beginning programmers.
Hogan
+4  A: 

You need to do a sub-query or a join, I think join is faster.

delete from teammembers
join teams on teammembers.teamid = teams.teamid
where teams.eventid = 1
Hogan
wow a down vote, who can know why
Hogan
@Hogan it was me by accident, sorry. I reverted it after editing your answer.
hobodave
np @hobodave, I don't mind them at all when I learn something new.
Hogan
Hogan: I didn't downvote your answer but your query is wrong. It will delete rows in the teams table too.
Mark Byers
@Mark - I saw that on hobodaves comments and answers. I think that is mysql only as this will work fine on mssql. Anyone know what the standard is?
Hogan
He didn't tag it as mysql, but he said in a comment that he is using mysql.
Mark Byers
A: 

This is what you want:

delete from teammembers where teamId in (select teamId from teams where eventId=1);

Edit: As some comments already suggest, the more efficient way is indeed through a join:

delete from teammebers
join teams on teams.teamId = teammembers.teamId
where eventId = 1
rmn
+2  A: 

You need to use the multi-table delete syntax:

DELETE teammembers
FROM teammembers
JOIN teams ON teamId=teams.teamId 
WHERE teams.eventId=1;

(I'm assuming MySQL here)

Mark Byers
+5  A: 

This is what I would do in SQL Server

DELETE tm 
--select tm.*
FROM teammembers tm
JOIN teams t on tm.teamId = t.teamId 
WHERE t.eventId = 1 

By embedding a select in the comment, I can run just this part manually and see what records I'm going to affect before I run the delete while I'm in development.

select tm.*
FROM teammembers tm
JOIN teams t on tm.teamId = t.teamId 
WHERE t.eventId = 1 

I never run a delete statment for the first time without checking to see that the records I think I'm going to delete are the records I intended to delete. This check will save you lots of worry as to whether your more complex deletes are affecting only the records you want to affect.

HLGEM
+1 for the good advice with the select in a comment.
Mark Byers
+1 thanks for the `--select` tip
Here Be Wolves