473,405 Members | 2,373 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

SELECT problem...

Hi,

I've got what I think (probably incorrectly) should be a simple SELECT :

Two colums with data like

col1 col2
1 50
1 51
2 50
2 51
3 50
3 54

I'm trying to bring back items in col1 that have values of both 50 and 51
( and potentially more numbers) in col 2

What we've got so far is:

SELECT contactid
FROM tblContactTypeToContact cttc
WHERE cttc.contactTypeID = 50
AND cttc.contactID IN (
SELECT contactID
FROM tblContactTypeToContact
WHERE contactTypeID IN (51)
)

Which I don't think is quite right :-)

Any help appreciated!

Cheers,

Ian

create table stuff below.
if exists (select * from dbo.sysobjects where id =
object_id(N'[dbo].[tblContactTypeToContact]') and OBJECTPROPERTY(id,
N'IsUserTable') = 1)
drop table [dbo].[tblContactTypeToContact]
GO

CREATE TABLE [dbo].[tblContactTypeToContact] (
[contactID] [int] NOT NULL ,
[contactTypeID] [int] NOT NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[tblContactTypeToContact] WITH NOCHECK ADD
CONSTRAINT [PK_tblContactTypeToContact] PRIMARY KEY CLUSTERED
(
[contactID],
[contactTypeID]
) ON [PRIMARY]
GO

INSERT tblContactTypeToContact (contactID, contactTypeID)
VALUES (1, 50)
INSERT tblContactTypeToContact (contactID, contactTypeID)
VALUES (1, 51)
INSERT tblContactTypeToContact (contactID, contactTypeID)
VALUES (2, 50)
INSERT tblContactTypeToContact (contactID, contactTypeID)
VALUES (2, 51)
INSERT tblContactTypeToContact (contactID, contactTypeID)
VALUES (3, 50)
INSERT tblContactTypeToContact (contactID, contactTypeID)
VALUES (3, 54)


Jul 20 '05 #1
3 3526
Your query looks correct to me but the following is easier to extend to any
number of values of contacttypeid:

SELECT contactid
FROM tblContactTypeToContact
WHERE contacttypeid IN (50,51)
GROUP BY contactid
HAVING COUNT(*)=2

If you need to be able to define the required types at runtime then put them
into another table first:

CREATE TABLE ContactTypes (contacttypeid INTEGER PRIMARY KEY)

INSERT INTO ContactTypes VALUES (50)
INSERT INTO ContactTypes VALUES (51)

SELECT C.contactid
FROM tblContactTypeToContact AS C
JOIN ContactTypes AS T
ON C.contacttypeid = T.contacttypeid
GROUP BY C.contactid
HAVING COUNT(*) =
(SELECT COUNT(*)
FROM ContactTypes)

--
David Portas
SQL Server MVP
--
Jul 20 '05 #2
Hiya,

Thanks for the very quick reply. That looks perfect.

We looked at that for at least an hour yesterday :-)

Cheers,

Ian

"David Portas" <RE****************************@acm.org> wrote in message
news:3L********************@giganews.com...
Your query looks correct to me but the following is easier to extend to any number of values of contacttypeid:

SELECT contactid
FROM tblContactTypeToContact
WHERE contacttypeid IN (50,51)
GROUP BY contactid
HAVING COUNT(*)=2

If you need to be able to define the required types at runtime then put them into another table first:

CREATE TABLE ContactTypes (contacttypeid INTEGER PRIMARY KEY)

INSERT INTO ContactTypes VALUES (50)
INSERT INTO ContactTypes VALUES (51)

SELECT C.contactid
FROM tblContactTypeToContact AS C
JOIN ContactTypes AS T
ON C.contacttypeid = T.contacttypeid
GROUP BY C.contactid
HAVING COUNT(*) =
(SELECT COUNT(*)
FROM ContactTypes)

--
David Portas
SQL Server MVP
--

Jul 20 '05 #3
Relational division is one of the eight basic operations in Codd's
relational algebra. The idea is that a divisor table is used to
partition a dividend table and produce a quotient or results table.
The quotient table is made up of those values of one column for which
a second column had all of the values in the divisor.

This is easier to explain with an example. We have a table of pilots
and the planes they can fly (dividend); we have a table of planes in
the hangar (divisor); we want the names of the pilots who can fly
every plane (quotient) in the hangar. To get this result, we divide
the PilotSkills table by the planes in the hangar.

CREATE TABLE PilotSkills
(pilot CHAR(15) NOT NULL,
plane CHAR(15) NOT NULL,
PRIMARY KEY (pilot, plane));

PilotSkills
pilot plane
=========================
'Celko' 'Piper Cub'
'Higgins' 'B-52 Bomber'
'Higgins' 'F-14 Fighter'
'Higgins' 'Piper Cub'
'Jones' 'B-52 Bomber'
'Jones' 'F-14 Fighter'
'Smith' 'B-1 Bomber'
'Smith' 'B-52 Bomber'
'Smith' 'F-14 Fighter'
'Wilson' 'B-1 Bomber'
'Wilson' 'B-52 Bomber'
'Wilson' 'F-14 Fighter'
'Wilson' 'F-17 Fighter'

CREATE TABLE Hangar
(plane CHAR(15) NOT NULL PRIMARY KEY);

Hangar
plane
=============
'B-1 Bomber'
'B-52 Bomber'
'F-14 Fighter'

PilotSkills DIVIDED BY Hangar
pilot
=============================
'Smith'
'Wilson'

In this example, Smith and Wilson are the two pilots who can fly
everything in the hangar. Notice that Higgins and Celko know how to
fly a Piper Cub, but we don't have one right now. In Codd's original
definition of relational division, having more rows than are called
for is not a problem.

The important characteristic of a relational division is that the
CROSS JOIN (Cartesian product) of the divisor and the quotient
produces a valid subset of rows from the dividend. This is where the
name comes from, since the CROSS JOIN acts like a multiplication
operator.

Division with a Remainder

There are two kinds of relational division. Division with a remainder
allows the dividend table to have more values than the divisor, which
was Codd's original definition. For example, if a pilot can fly more
planes than just those we have in the hangar, this is fine with us.
The query can be written in SQL-89 as

SELECT DISTINCT pilot
FROM PilotSkills AS PS1
WHERE NOT EXISTS
(SELECT *
FROM Hangar
WHERE NOT EXISTS
(SELECT *
FROM PilotSkills AS PS2
WHERE (PS1.pilot = PS2.pilot)
AND (PS2.plane = Hangar.plane)));

The quickest way to explain what is happening in this query is to
imagine an old World War II movie where a cocky pilot has just walked
into the hangar, looked over the fleet, and announced, "There ain't no
plane in this hangar that I can't fly!" We are finding the pilots for
whom there does not exist a plane in the hangar for which they have no
skills. The use of the NOT EXISTS() predicates is for speed. Most
SQL systems will look up a value in an index rather than scan the
whole table. The SELECT * clause lets the query optimizer choose the
column to use when looking for the index.

This query for relational division was made popular by Chris Date in
his textbooks, but it is not the only method nor always the fastest.
Another version of the division can be written so as to avoid three
levels of nesting. While it is not original with me, I have made it
popular in my books.

SELECT PS1.pilot
FROM PilotSkills AS PS1, Hangar AS H1
WHERE PS1.plane = H1.plane
GROUP BY PS1.pilot
HAVING COUNT(PS1.plane) = (SELECT COUNT(plane) FROM Hangar);

There is a serious difference in the two methods. Burn down the
hangar, so that the divisor is empty. Because of the NOT EXISTS()
predicates in Date's query, all pilots are returned from a division by
an empty set. Because of the COUNT() functions in my query, no pilots
are returned from a division by an empty set.

In the sixth edition of his book, INTRODUCTION TO DATABASE SYSTEMS
(Addison-Wesley; 1995 ;ISBN 0-201-82458-2), Chris Date defined another
operator (DIVIDEBY ... PER) which produces the same results as my
query, but with more complexity.

Exact Division

The second kind of relational division is exact relational division.
The dividend table must match exactly to the values of the divisor
without any extra values.

SELECT PS1.pilot
FROM PilotSkills AS PS1
LEFT OUTER JOIN
Hangar AS H1
ON PS1.plane = H1.plane
GROUP BY PS1.pilot
HAVING COUNT(PS1.plane) = (SELECT COUNT(plane) FROM Hangar)
AND COUNT(H1.plane) = (SELECT COUNT(plane) FROM Hangar);

This says that a pilot must have the same number of certificates as
there planes in the hangar and these certificates all match to a plane
in the hangar, not something else. The "something else" is shown by a
created NULL from the LEFT OUTER JOIN.

Please do not make the mistake of trying to reduce the HAVING clause
with a little algebra to:

HAVING COUNT(PS1.plane) = COUNT(H1.plane)

because it does not work; it will tell you that the hangar has (n)
planes in it and the pilot is certified for (n) planes, but not that
those two sets of planes are equal to each other.

Note on Performance

The nested EXISTS() predicates version of relational division was made
popular by Chris Date's textbooks, while the author is associated with
popularizing the COUNT(*) version of relational division. The Winter
1996 edition of DB2 ON-LINE MAGAZINE
(http://www.db2mag.com/96011ar:htm) had an article entitled "Powerful
SQL:Beyond the Basics" by Sheryl Larsen which gave the results of
testing both methods. Her conclusion for DB2 was that the nested
EXISTS() version is better when the quotient has less than 25% of the
dividend table's rows and the COUNT(*) version is better when the
quotient is more than 25% of the dividend table.
Jul 20 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: D. Shifflett | last post by:
Hi all, I am having trouble with a program that ran fine on Python 2.0 (#0, Mar 1 2001, 01:47:55) on linux2 but will not work on Python 2.3.2 (#1, Oct 8 2003, 17:33:47) on linux2
2
by: RanDeep | last post by:
I have two nodes that both exist underneath the root node. They are linked, however, in the sense that one of the nodes contains a copy of an id that is used to refer to the other. However, when I...
3
by: Dennis M. Marks | last post by:
I have a problem with the following code. It generates a <FORM><SELECT><OPTION> list. There is no problem in the generating. The problem is in the execution as follows. It works fine in Mac IE...
3
by: Tcs | last post by:
My backend is DB2 on our AS/400. While I do HAVE DB2 PE for my PC, I haven't loaded it yet. I'm still using MS Access. And no, I don't believe this is an Access question. (But who knows? I...
1
by: Andrew McNab | last post by:
Hi folks, I have a problem with an MS Access SQL query which is being used in an Access Report, and am wondering if anyone can help. Basically, my query (shown below) gets some records from a...
2
by: Chris Plowman | last post by:
Hi all, I was wondering if anyone can help me with a really annoying problem I have been having. I made a derived datagrid class that will select the row when a user clicks anywhere on a cell...
2
by: areef.islam | last post by:
Hi, I am kinda new to javascript and I am having this problem with selecting multiple options from a select tag. Hope someone can help me out here. here is my code...
3
by: imrantbd | last post by:
This is my first problem.Please help me. I have the following code: <head> <script language="JavaScript"> function addSrcToDestList() { destList1 = window.document.forms.destList; srcList...
13
by: PinkBishop | last post by:
I am using VS 2005 with a formview control trying to insert a record to my access db. The data is submitted to the main table no problem, but I need to carry the catID to the bridge table...
2
by: djnokturnal | last post by:
Hey guys / gals, First time posting and of course I am sure it is something that has been answered 100 times but for some reason I just cant find the answer :) First off here is the structure...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.