dbTalk Databases Forums  

SQL query question.

comp.databases.ms-sqlserver comp.databases.ms-sqlserver


Discuss SQL query question. in the comp.databases.ms-sqlserver forum.



Reply
 
Thread Tools Display Modes
  #1  
Old   
danny
 
Posts: n/a

Default SQL query question. - 11-01-2007 , 12:03 AM






Hate to ask trivial questions on newsgroup but I've had no luck on
google, IRC, or a 500 page SQL book. Long story short I'm creating a
instant messaging web site that allows people to block messages from
specific users (spammers, etc)

Here's what the 2 tables look like

TABLE: USERS
---------------------------------------
Quote:
USER EMAIL | USER NAME, ETC...
dave@a.com |
candy@a.com |
bob@a.com |
sherry@a.com|
---------------------------------------

TABLE: BLOCKED_USERS
---------------------------------------
Quote:
USER EMAIL | BLOCKED_EMAIL
dave@a.com | bob@a.com
candy@a.com | dave@a.com
candy@a.com | bob@a.com
---------------------------------------

Mind you when the user fires off a message their EMAIL address is passed
off to the stored procedure (which I'm having the trouble on). User Bob
sends out a message - calling the following SQL (HENCE - his email
address is in the WHERE clause to find out if he has anyone blocking
him. And get a list of email address of all the recipients who are NOT
blocking Bob).

************************************************** *****
SELECT USERS.email
FROM USERS
LEFT OUTER JOIN
BLOCKED_USERS ON USERS.email = BLOCKED_USERS.user_email
WHERE
(BLOCKED_USERS.blocked_email <> 'bob@a.com')
OR
(BLOCKED_USERS.blocked_email IS NULL)
************************************************** *****

Firing the SQL produces...

************************************************** *****
EMAIL
--------------
bob@a.com
sherry@a.com
candy@a.com
************************************************** *****

This is the wrong results. First Bob would get a message to himself
since he is not in the BLOCKED_USERS table (JOINed on BLOCKED_USERS and
USERS in the column email address). Secondly Candy would receive Bob's
message (but Candy has Bob on the BLOCK_USERS list).

The correct result should return sherry@a.com ONLY.

I know what's causing the two issues and it's the JOIN. Would someone
PLEASE help me out with a better SQL.


Reply With Quote
  #2  
Old   
Roy Harvey (SQL Server MVP)
 
Posts: n/a

Default Re: SQL query question. - 11-01-2007 , 06:06 AM






What is causing the problem is

Quote:
(BLOCKED_USERS.blocked_email <> 'bob@a.com')
This turns the LEFT OUTER join into an INNER join by eliminating all
the NULL BLOCKED_USERS as the NULLs fail this test.

One fix is to move this test to the ON clause of the LEFT OUTER JOIN
with an AND. Another is to use NOT EXISTS instead.

SELECT A.email
FROM USERS as A
WHERE NOT EXISTS
(SELECT *
FROM BLOCKED_USERS as B
WHERE A.email = B.user_email)
AND A.email <> 'bob@a.com'

Roy Harvey
Beacon Falls, CT

On Thu, 01 Nov 2007 02:03:15 -0400, danny <teddy (AT) woh (DOT) rr.com> wrote:

Quote:
Hate to ask trivial questions on newsgroup but I've had no luck on
google, IRC, or a 500 page SQL book. Long story short I'm creating a
instant messaging web site that allows people to block messages from
specific users (spammers, etc)

Here's what the 2 tables look like

TABLE: USERS
---------------------------------------
| USER EMAIL | USER NAME, ETC...
| dave@a.com |
| candy@a.com |
| bob@a.com |
| sherry@a.com|
---------------------------------------

TABLE: BLOCKED_USERS
---------------------------------------
| USER EMAIL | BLOCKED_EMAIL
| dave@a.com | bob@a.com
| candy@a.com | dave@a.com
| candy@a.com | bob@a.com
---------------------------------------

Mind you when the user fires off a message their EMAIL address is passed
off to the stored procedure (which I'm having the trouble on). User Bob
sends out a message - calling the following SQL (HENCE - his email
address is in the WHERE clause to find out if he has anyone blocking
him. And get a list of email address of all the recipients who are NOT
blocking Bob).

************************************************** *****
SELECT USERS.email
FROM USERS
LEFT OUTER JOIN
BLOCKED_USERS ON USERS.email = BLOCKED_USERS.user_email
WHERE
(BLOCKED_USERS.blocked_email <> 'bob@a.com')
OR
(BLOCKED_USERS.blocked_email IS NULL)
************************************************** *****

Firing the SQL produces...

************************************************** *****
EMAIL
--------------
bob@a.com
sherry@a.com
candy@a.com
************************************************** *****

This is the wrong results. First Bob would get a message to himself
since he is not in the BLOCKED_USERS table (JOINed on BLOCKED_USERS and
USERS in the column email address). Secondly Candy would receive Bob's
message (but Candy has Bob on the BLOCK_USERS list).

The correct result should return sherry@a.com ONLY.

I know what's causing the two issues and it's the JOIN. Would someone
PLEASE help me out with a better SQL.

Reply With Quote
  #3  
Old   
Dan Guzman
 
Posts: n/a

Default Re: SQL query question. - 11-01-2007 , 06:37 AM



Quote:
I know what's causing the two issues and it's the JOIN. Would someone
PLEASE help me out with a better SQL.
I suggest you use NOT EXISTS instead of LEFT OUTER JOIN for your
requirements. This will ensure you don't get the same user back multiple
times in cases where a user has blocked multiple users. Below is a sample
proc:

CREATE PROCEDURE dbo.GetUserList
@user_email varchar(255)
AS
SET NOCOUNT ON

SELECT
USERS.email
FROM dbo.USERS
WHERE
USERS.email <> @user_email --exclude self
AND NOT EXISTS --exclude blocking users
(
SELECT *
FROM dbo.BLOCKED_USERS
WHERE
USERS.email = BLOCKED_USERS.user_email
AND BLOCKED_USERS.blocked_email = @user_email
)

RETURN @@ERROR
GO

--
Hope this helps.

Dan Guzman
SQL Server MVP

"danny" <teddy (AT) woh (DOT) rr.com> wrote

Quote:
Hate to ask trivial questions on newsgroup but I've had no luck on google,
IRC, or a 500 page SQL book. Long story short I'm creating a instant
messaging web site that allows people to block messages from specific
users (spammers, etc)

Here's what the 2 tables look like

TABLE: USERS
---------------------------------------
| USER EMAIL | USER NAME, ETC...
| dave@a.com |
| candy@a.com |
| bob@a.com |
| sherry@a.com|
---------------------------------------

TABLE: BLOCKED_USERS
---------------------------------------
| USER EMAIL | BLOCKED_EMAIL
| dave@a.com | bob@a.com
| candy@a.com | dave@a.com
| candy@a.com | bob@a.com
---------------------------------------

Mind you when the user fires off a message their EMAIL address is passed
off to the stored procedure (which I'm having the trouble on). User Bob
sends out a message - calling the following SQL (HENCE - his email address
is in the WHERE clause to find out if he has anyone blocking him. And get
a list of email address of all the recipients who are NOT blocking Bob).

************************************************** *****
SELECT USERS.email
FROM USERS
LEFT OUTER JOIN
BLOCKED_USERS ON USERS.email = BLOCKED_USERS.user_email
WHERE
(BLOCKED_USERS.blocked_email <> 'bob@a.com')
OR
(BLOCKED_USERS.blocked_email IS NULL)
************************************************** *****

Firing the SQL produces...

************************************************** *****
EMAIL
--------------
bob@a.com
sherry@a.com
candy@a.com
************************************************** *****

This is the wrong results. First Bob would get a message to himself since
he is not in the BLOCKED_USERS table (JOINed on BLOCKED_USERS and USERS in
the column email address). Secondly Candy would receive Bob's message (but
Candy has Bob on the BLOCK_USERS list).

The correct result should return sherry@a.com ONLY.

I know what's causing the two issues and it's the JOIN. Would someone
PLEASE help me out with a better SQL.


Reply With Quote
  #4  
Old   
Ed Murphy
 
Posts: n/a

Default Re: SQL query question. - 11-01-2007 , 08:03 PM



Roy Harvey (SQL Server MVP) wrote:

Quote:
What is causing the problem is

(BLOCKED_USERS.blocked_email <> 'bob@a.com')

This turns the LEFT OUTER join into an INNER join by eliminating all
the NULL BLOCKED_USERS as the NULLs fail this test.
But they'll pass the other part of the test:

OR
(BLOCKED_USERS.blocked_email IS NULL)

That said, I agree that NOT EXISTS is the right way to go.


Reply With Quote
  #5  
Old   
danny
 
Posts: n/a

Default Re: SQL query question. - 11-01-2007 , 10:57 PM



thanks for the help people

danny wrote:
Quote:
Hate to ask trivial questions on newsgroup but I've had no luck on
google, IRC, or a 500 page SQL book. Long story short I'm creating a
instant messaging web site that allows people to block messages from
specific users (spammers, etc)

Here's what the 2 tables look like

TABLE: USERS
---------------------------------------
| USER EMAIL | USER NAME, ETC...
| dave@a.com |
| candy@a.com |
| bob@a.com |
| sherry@a.com|
---------------------------------------

TABLE: BLOCKED_USERS
---------------------------------------
| USER EMAIL | BLOCKED_EMAIL
| dave@a.com | bob@a.com
| candy@a.com | dave@a.com
| candy@a.com | bob@a.com
---------------------------------------

Mind you when the user fires off a message their EMAIL address is passed
off to the stored procedure (which I'm having the trouble on). User Bob
sends out a message - calling the following SQL (HENCE - his email
address is in the WHERE clause to find out if he has anyone blocking
him. And get a list of email address of all the recipients who are NOT
blocking Bob).

************************************************** *****
SELECT USERS.email
FROM USERS
LEFT OUTER JOIN
BLOCKED_USERS ON USERS.email = BLOCKED_USERS.user_email
WHERE
(BLOCKED_USERS.blocked_email <> 'bob@a.com')
OR
(BLOCKED_USERS.blocked_email IS NULL)
************************************************** *****

Firing the SQL produces...

************************************************** *****
EMAIL
--------------
bob@a.com
sherry@a.com
candy@a.com
************************************************** *****

This is the wrong results. First Bob would get a message to himself
since he is not in the BLOCKED_USERS table (JOINed on BLOCKED_USERS and
USERS in the column email address). Secondly Candy would receive Bob's
message (but Candy has Bob on the BLOCK_USERS list).

The correct result should return sherry@a.com ONLY.

I know what's causing the two issues and it's the JOIN. Would someone
PLEASE help me out with a better SQL.

Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.3
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.