Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
pinecrest515
Starting Member
11 Posts |
Posted - 2010-12-08 : 10:04:58
|
Dear Forumers,I figured out that my previous SQL statement, which I thought solved a problem, doesn't:Suppose I have the following table:First_Name Last_Name Age_Group Vaccinated AgeJohn Smith Adult Yes 30Mary Smith Child Yes 5Casey Smith Child No 12Joe Smith Child No 6Sam Walton Adult Yes 31Thomas Walton Child No 15John Walton Child Yes 5Mary Scott Adult Yes 56Andrew Johnson Adult Yes 55Bryon Johnson Child No 12I am trying to query for a list of Adults that have all their children (who have same last name) either Vaccinated or over the age of 10.Ideally, the query should output the following:First_Name Last_Name Age_Group Vaccinated AgeSam Walton Adult Yes 31Andrew Johnson Adult Yes 55Sam Walton is returned, because he has 1 child over 15 and 1 child vaccinated.Andrew Johnson is returned, because although his child is not vaccinated, the child is over 10 years old.John Smith is not returned, because although 2 of his children are either vaccinated or over 10, the third child is not vaccinated and under 10.Mary Scott is not returned, because she has no children.Currently, my query finds a list of Adults that have at least one child vaccinated or one child over 10. If an adult has one child under 10 who is not vaccinated, but has another child over 10 or vaccinated, then the query will still return the adult's record. This is not robust - I would like only adults who have all their children either vaccinated or over 10.My current, un-robust query:SELECT DISTINCTA.*FROM [Table1] AS [A]INNER JOIN[Table1] AS [B]ON [A].[Last_Name] = [B].[Last_Name]WHERE[A].[Age_Group] = 'Adult'AND [B].[Age_Group] = 'Child'AND([B].[Vaccinated] = 'Yes' OR [B].[Age] > 10 )Currently, my un-robust query is outputting the following:First_Name Last_Name Age_Group Vaccinated AgeSam Walton Adult Yes 31John Smith Adult Yes 30Andrew Johnson Adult Yes 55How should I best construct this query to achieve the desired results?Thanks in advance for your reply! |
|
Ifor
Aged Yak Warrior
700 Posts |
Posted - 2010-12-08 : 10:34:42
|
quote: Originally posted by pinecrest515 Dear Forumers,I figured out that my previous SQL statement, which I thought solved a problem, doesn't:Suppose I have the following table:First_Name Last_Name Age_Group Vaccinated AgeJohn Smith Adult Yes 30Mary Smith Child Yes 5Casey Smith Child No 12Joe Smith Child No 6Sam Walton Adult Yes 31Thomas Walton Child No 15John Walton Child Yes 5Mary Scott Adult Yes 56Andrew Johnson Adult Yes 55Bryon Johnson Child No 12I am trying to query for a list of Adults that have all their children (who have same last name) either Vaccinated or over the age of 10.Ideally, the query should output the following:First_Name Last_Name Age_Group Vaccinated AgeSam Walton Adult Yes 31Andrew Johnson Adult Yes 55Sam Walton is returned, because he has 1 child over 15 and 1 child vaccinated.Andrew Johnson is returned, because although his child is not vaccinated, the child is over 10 years old.John Smith is not returned, because although 2 of his children are either vaccinated or over 10, the third child is not vaccinated and under 10.Mary Scott is not returned, because she has no children.Currently, my query finds a list of Adults that have at least one child vaccinated or one child over 10. If an adult has one child under 10 who is not vaccinated, but has another child over 10 or vaccinated, then the query will still return the adult's record. This is not robust - I would like only adults who have all their children either vaccinated or over 10.My current, un-robust query:SELECT DISTINCTA.*FROM [Table1] AS [A]INNER JOIN[Table1] AS [B]ON [A].[Last_Name] = [B].[Last_Name]WHERE[A].[Age_Group] = 'Adult'AND [B].[Age_Group] = 'Child'AND([B].[Vaccinated] = 'Yes' OR [B].[Age] > 10 )Currently, my un-robust query is outputting the following:First_Name Last_Name Age_Group Vaccinated AgeSam Walton Adult Yes 31John Smith Adult Yes 30Andrew Johnson Adult Yes 55How should I best construct this query to achieve the desired results?Thanks in advance for your reply!
Anything that relies on Last_Name to link a Child to a parent cannot be described as robust.Something like the following may help:SELECT A.*FROM Table1 A JOIN ( SELECT C.Last_Name FROM Table1 C WHERE C.Age_Group = 'Child' GROUP BY C.Last_Name HAVING COUNT(*) = SUM(CASE WHEN C.Vaccinated = 'Yes' OR C.Age > 10 THEN 1 ELSE 0 END) ) D ON A.Last_Name = D.Last_NameWHERE A.Age_Group = 'Adult' |
 |
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2010-12-08 : 10:58:20
|
I prefer scanning the table just once.DECLARE @Sample TABLE ( FirstName VARCHAR(20), LastName VARCHAR(20), AgeGroup VARCHAR(20), Vaccinated VARCHAR(3), Age TINYINT )INSERT @Sample ( FirstName, LastName, AgeGroup, Vaccinated, Age )SELECT 'John', 'Smith', 'Adult', 'Yes', 30 UNION ALLSELECT 'Mary', 'Smith', 'Child', 'Yes', 5 UNION ALLSELECT 'Casey', 'Smith', 'Child', 'No', 12 UNION ALLSELECT 'Joe', 'Smith', 'Child', 'No', 6 UNION ALLSELECT 'Sam', 'Walton', 'Adult', 'Yes', 31 UNION ALLSELECT 'Thomas', 'Walton', 'Child', 'No', 15 UNION ALLSELECT 'John', 'Walton', 'Child', 'Yes', 5 UNION ALLSELECT 'Mary', 'Scott', 'Adult', 'Yes', 56 UNION ALLSELECT 'Andrew', 'Johnson', 'Adult', 'Yes', 55 UNION ALLSELECT 'Bryon', 'Johnson', 'Child', 'No' , 12-- IforSELECT a.*FROM @Sample AS aINNER JOIN ( SELECT LastName FROM @Sample WHERE AgeGroup = 'Child' GROUP BY LastName HAVING COUNT(*) = SUM(CASE WHEN Vaccinated = 'Yes' OR Age > 10 THEN 1 ELSE 0 END) ) AS d ON d.LastName = a.LastNameWHERE a.AgeGroup = 'Adult'-- PesoSELECT FirstName, LastName, AgeGroup, Vaccinated, AgeFROM ( SELECT FirstName, LastName, AgeGroup, Vaccinated, Age, MIN(CASE WHEN AgeGroup = 'Adult' THEN 2 WHEN Vaccinated = 'Yes' OR Age > 10 THEN 1 ELSE 0 END) OVER (PARTITION BY LastName) AS Value FROM @Sample ) AS dWHERE AgeGroup = 'Adult' AND Value = 1 N 56°04'39.26"E 12°55'05.63" |
 |
|
|
|
|
|
|