I have a data set where 1 column may have 2 different values for each ID. I want to know if there is a way to find out which IDs don't have one of the values.
Here's what a sample of my data set looks like.
Object ID | Relate Type
------------------------
1 | P
1 | S
2 | P
3 | S
4 | P
4 | S
And I want to write a query that will tell me which Objet ID does not have a Relate Type of S.
This was my first attempt:
SELECT [obj_id], COUNT([obj_id]) AS [Successor Count]
FROM [Prim].[dbo].[relations]
WHERE [relate_type] = 'S'
GROUP BY [obj_id]
After thinking about it for a little bit, I realized that this will never give me a Successor Count of 0 because I am specifically querying the Object IDs that have a Relate Type of S. Knowing this, I decided I would probably need some kind of sub query and then I came up with these 2 solutions:
SELECT [obj_id]
FROM [Prim].[dbo].[relations]
WHERE NOT EXISTS
(SELECT DISTINCT [obj_id], [relate_type]
FROM [Prim].[dbo].[relations]
WHERE relate_type = 'S')
The above solution doesn't give me the right answer. At least I'm pretty sure it doesn't. Either way, it takes 2.5 minutes to run on a relatively small dataset of 700,000 entries.
The below query I'm pretty sure works and it runs quickly. But I was wondering if there was a different way to do this.
SELECT A.[obj_id]
FROM [Prim].[dbo].[relations] A
LEFT JOIN
(SELECT DISTINCT [obj_id], [relate_type]
FROM [Prim].[dbo].[relations]
WHERE [relate_type] = 'S') B ON A.[obj_id] = B.[obj_id]
WHERE A.[relate_type] != 'S' AND B.[obj_id] IS NULL
This should work:
SELECT *
FROM [Prim].[dbo].[relations] r
WHERE NOT EXISTS(SELECT 1 FROM [Prim].[dbo].[relations]
WHERE [relate_type] = 'S'
AND obj_id = r.obj_id)
I came up with this other option. Tell me if this is faster in your case. :)
SELECT [obj_id]
FROM [Prim].[dbo].[relations]
GROUP BY [obj_id]
HAVING MAX(CASE WHEN [relate_type] = 'S' THEN 1 ELSE 0 END) = 0
From your question it looks like you want a list of all id's that are missing either one of the values. This will give you a list of [obj_id]
With the [relate_type]
that is missing (expanding on a previous answer)
SELECT [obj_id],
CASE WHEN [relate_type] = 'P' THEN 'S'
END AS [relate type missing]
FROM [Prim].[dbo].[relations] r
WHERE NOT EXISTS(SELECT 1 FROM [Prim].[dbo].[relations]
WHERE [relate type] = 'S'
AND [obj_id] = r.[obj_id])
UNION
SELECT [obj_id],
CASE WHEN [relate_type] = 'S' THEN 'P'
END AS [relate type missing]
FROM [Prim].[dbo].[relations] r
WHERE NOT EXISTS(SELECT 1 FROM [Prim].[dbo].[relations]
WHERE [relate type] = 'P'
AND [obj_id] = r.[obj_id])
You can use either of the two queries to get a list for just missing S
or P
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.