What is the SQL Contruct for returning records based on target conditions for the same Column.
-
Tuesday, March 06, 2012 11:32 PM
What is the SQL construct to return the records where doc_type equals all three conditions of A, B and C and excludes all the others.
Meaning in the example below that only the records for PD_ID 2901 and 2905 would be returned because they are the only ones that have all 3 values of A, B and C for the Doc_Type Column.For the example Table [TestTable]
id PD_ID doc_type datetime
1 2901 A 2/1/2012
2 2901 B 2/2/2012
3 2901 C 2/3/2012
4 2902 A 2/4/2012
5 2902 A 2/5/2012
6 2903 B 2/6/2012
7 2903 B 2/6/2012
8 2904 C 2/7/2012
9 2905 A 2/8/2012
10 2905 A 2/9/2012
11 2905 B 2/10/2012
12 2905 B 2/10/2012
14 2905 C 2/11/2012
Script to Create Table
----------------------
SET ANSI_NULLS ONGO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[TestTable](
[id] [int] IDENTITY(1,1) NOT NULL,
[PD_ID] [int] NULL,
[doc_type] [varchar](15) NULL,
[date] [datetime] NOT NULL,
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
Script to Insert Data
----------------------
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2901, 'A', Convert(Datetime,'2/1/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2901, 'B', Convert(Datetime,'2/2/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2901, 'C', Convert(Datetime,'2/3/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2902, 'A', Convert(Datetime,'2/4/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2902, 'A', Convert(Datetime,'2/5/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2903, 'B', Convert(Datetime,'2/6/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2903, 'B', Convert(Datetime,'2/6/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2904, 'C', Convert(Datetime,'2/7/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2905, 'A', Convert(Datetime,'2/8/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2905, 'A', Convert(Datetime,'2/9/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2905, 'B', Convert(Datetime,'2/10/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2905, 'B', Convert(Datetime,'2/10/2012'))
INSERT INTO TestTable (PD_ID, doc_type, date)
VALUES (2905, 'C', Convert(Datetime,'2/11/2012'))
All Replies
-
Tuesday, March 06, 2012 11:48 PM
Are you looking for something like this:
Declare @TestTable Table( [id] [int] IDENTITY(1,1) NOT NULL, [PD_ID] [int] NULL, [doc_type] [varchar](15) NULL, [date] [datetime] NOT NULL) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2901, 'A', Convert(Datetime,'2/1/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2901, 'B', Convert(Datetime,'2/2/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2901, 'C', Convert(Datetime,'2/3/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2902, 'A', Convert(Datetime,'2/4/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2902, 'A', Convert(Datetime,'2/5/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2903, 'B', Convert(Datetime,'2/6/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2903, 'B', Convert(Datetime,'2/6/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2904, 'C', Convert(Datetime,'2/7/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2905, 'A', Convert(Datetime,'2/8/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2905, 'A', Convert(Datetime,'2/9/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2905, 'B', Convert(Datetime,'2/10/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2905, 'B', Convert(Datetime,'2/10/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2905, 'C', Convert(Datetime,'2/11/2012')) INSERT INTO @TestTable (PD_ID, doc_type, date) VALUES (2906, 'C', Convert(Datetime,'2/11/2012')) Select * From @TestTable As MainQry Where Exists (Select 1 From @TestTable As SubQry Where SubQry.doc_type In ('A', 'B', 'C') And SubQry.PD_ID = MainQry.PD_ID Group By SubQry.PD_ID Having Count(Distinct Doc_type) = 3) --output id PD_ID doc_type date 1 2901 A 2012-02-01 00:00:00.000 2 2901 B 2012-02-02 00:00:00.000 3 2901 C 2012-02-03 00:00:00.000 9 2905 A 2012-02-08 00:00:00.000 10 2905 A 2012-02-09 00:00:00.000 11 2905 B 2012-02-10 00:00:00.000 12 2905 B 2012-02-10 00:00:00.000 13 2905 C 2012-02-11 00:00:00.000
Best Wishes, Arbi; Please vote if you find this posting was helpful or Mark it as answered.
- Edited by Arbi Baghdanian Wednesday, March 07, 2012 12:07 AM correction
- Proposed As Answer by Eshani Rao Wednesday, March 07, 2012 2:17 AM
- Marked As Answer by Naomi NMicrosoft Community Contributor, Moderator Wednesday, March 07, 2012 2:57 PM
-
Tuesday, March 06, 2012 11:53 PM
SELECT PD_ID FROM TestTable WHERE Doc_Type = 'A' INTERSECT SELECT PD_ID FROM TestTable WHERE Doc_Type = 'B' INTERSECT SELECT PD_ID FROM TestTable WHERE Doc_Type = 'C'
This will give you the PD_ID, if you want to expand the columns you will have to add
SELECT * FROM TestTable WHERE PD_ID IN ({above code})
Best Wishes, The Redman; If something helps, please help show it by voting, if it solves, bonus!
- Marked As Answer by Naomi NMicrosoft Community Contributor, Moderator Wednesday, March 07, 2012 2:57 PM
-
Wednesday, March 07, 2012 12:02 AM
Maybe something along these lines might helpWITH t1 AS( SELECT DISTINCT PD_ID, doc_type FROM TestTable ), t2 AS( SELECT PD_ID, Count(*) as valid_count FROM t1 GROUP BY PD_ID ) SELECT * FROM t2 WHERE valid_count =3- Marked As Answer by Naomi NMicrosoft Community Contributor, Moderator Wednesday, March 07, 2012 2:58 PM
-
Wednesday, March 07, 2012 12:27 AM
Short answer: you want an exact relational division. This was one of Dr. Codd's original 8 operations and there are several ways to do it. I will get ot that
Better answer: Your SQL needs to be cleaned up. CONVERT() is an old Sybase left over; we have CAST() now. But since we have a DATE data type, that code was a waste of time. And SQL use ISO-8601 date formatsThere is no such thing as a generic magical “id” in RDBMS; that was physical record numbers in the old days. Bad SQL programmers will use IDENTITY to fake it. But it is not a key.
You do not know ISO-11179 naming rules, etc. What you posted was a mag tape file written in bad SQL Here is a clean up; see the constraints? Proper key instead of an absurd IDENTITY? Formatted dates?
CREATE TABLE Something_Tests
(test_id INTEGER NOT NULL,
test_type CHAR(1) NOT NULL
CHECK (doc_type IN ('A','B','C')),
PRIMARY KEY (test_id, test_type, test_date),
test_date DATE NOT NULL);
We have row constructor syntax now:
INSERT INTO Something_Tests (test_id, test_type, test_date)
VALUES
(2901, 'A', '2012-02-01'), (2901, 'B', '2012-02-02'),
(2901, 'C', '2012-02-03'),
(2902, 'A', '2012-02-04'), (2902, 'A', '2012-02-05'),
(2903, 'B', '2012-02-06'), (2903, 'B', '2012-02-06'),
(2904, 'C', '2012-02-07'),
(2905, 'A', '2012-02-08'), (2905, 'A', '2012-02-09'),
(2905, 'B', '2012-02-00'), (2905, 'B', '2012-02-10'),
(2905, 'C', '2012-02-11');
You have a fixed divisor, the set {'A','B','C'}, so we can write it this way;
SELECT test_id
FROM Something_Tests
GROUP BY test_id
HAVING COUNT(*) = 3
AND COUNT(DISTINCT test_type) = 3;
You can Google more general forms of Relational Division that will work for division with remainders, and general divisors.
--CELKO-- Books in Celko Series for Morgan-Kaufmann Publishing: Analytics and OLAP in SQL / Data and Databases: Concepts in Practice Data / Measurements and Standards in SQL SQL for Smarties / SQL Programming Style / SQL Puzzles and Answers / Thinking in Sets / Trees and Hierarchies in SQL
- Marked As Answer by Naomi NMicrosoft Community Contributor, Moderator Wednesday, March 07, 2012 2:58 PM
-
Wednesday, March 07, 2012 2:13 PMWow! Thank you to GGoldspink, Arbi, jtclipper, and CELKO. All four answers were very valuable.
GGoldspink, I was able to most quickly apply your solution to my pre-existing situation and it resolved the problem.
Thank you to all.- Marked As Answer by Tomb421 Wednesday, March 07, 2012 2:13 PM
- Unmarked As Answer by Naomi NMicrosoft Community Contributor, Moderator Wednesday, March 07, 2012 2:57 PM

