TSQL - How to get a record satisfies a condition without excluding others that do not











up vote
0
down vote

favorite












It seems pretty simple but I have not touched SQL for years. When I come back , totally stuck with this math. Let say I have 3 tables as below:



Table Name:



|NameId| Name |
|------|------|
| 1 | John |
| 2 | Doe |
| 3 | Brian|


Table Tag:



|TagId| Tag     |
|-----|---------|
| 1 | Teacher |
| 2 | Engineer|
| 3 | Employee|


Table NameTag:



|NameId|TagId|
|---- |-----|
|1 | 1 |
|2 | 2 |
|2 | 3 |
|3 | 3 |


I want to find all names along with associated tags by a tag. E.g. find names with tag Employee (TagId = 3). I expect result like this:



|NameId|TagId|
|---- |-----|
|2 | 2 |
|2 | 3 |
|3 | 3 |


How can I achieve that in a T-SQL script?



I tried with script below but it always excludes the records 1|1 and 2|2:



SELECT *
FROM NameTag
WHERE TagId = 3


Result I do not expect:



|NameId|TagId|
|---- |-----|
|2 | 3 |
|3 | 3 |




UPDATE



Looks like there are many solutions commented below as @plax, @SteveB or @picklerick and some others pointed. I have not had a chance to test all of them but they seem working for me. Thank you all! (early thanksgiving today for me).



By that time, I have also found a solution myself and posted here for reference. Also, @plax pointed out below.



My solution:



--Get persons that have the tag.
WITH Person_CTE AS
(
SELECT DISTINCT NameId
FROM NameTag
WHERE TagId = 3
)
-- Looking other tags for the person.
SELECT *
FROM NameTag nt
JOIN Person_CTE p ON nt.NameId = p.NameId


Another solution as @plalx has pointed out that was written very clearly:





  1. Find all NameId that have an associated TagId of 3. E.g.



    SELECT NameId
    FROM NameTag
    WHERE TagId = 3



  2. Find all tags for NameId we found in step #1.



    SELECT NameId, TagId
    FROM NameTag
    WHERE NameId IN
    (-- Solution from #1
    SELECT NameId
    FROM NameTag
    WHERE TagId = 3)











share|improve this question
























  • So you want a resultset with All names for a tag and all the tags for those names?
    – SteveB
    Nov 21 at 21:26










  • So... What are the results that you DO want?
    – Jason A. Long
    Nov 21 at 21:27










  • @SteveB: yes, I do want that.
    – Thang Nguyen
    Nov 21 at 23:08










  • @JasonA.Long: I did say in the post.
    – Thang Nguyen
    Nov 21 at 23:08















up vote
0
down vote

favorite












It seems pretty simple but I have not touched SQL for years. When I come back , totally stuck with this math. Let say I have 3 tables as below:



Table Name:



|NameId| Name |
|------|------|
| 1 | John |
| 2 | Doe |
| 3 | Brian|


Table Tag:



|TagId| Tag     |
|-----|---------|
| 1 | Teacher |
| 2 | Engineer|
| 3 | Employee|


Table NameTag:



|NameId|TagId|
|---- |-----|
|1 | 1 |
|2 | 2 |
|2 | 3 |
|3 | 3 |


I want to find all names along with associated tags by a tag. E.g. find names with tag Employee (TagId = 3). I expect result like this:



|NameId|TagId|
|---- |-----|
|2 | 2 |
|2 | 3 |
|3 | 3 |


How can I achieve that in a T-SQL script?



I tried with script below but it always excludes the records 1|1 and 2|2:



SELECT *
FROM NameTag
WHERE TagId = 3


Result I do not expect:



|NameId|TagId|
|---- |-----|
|2 | 3 |
|3 | 3 |




UPDATE



Looks like there are many solutions commented below as @plax, @SteveB or @picklerick and some others pointed. I have not had a chance to test all of them but they seem working for me. Thank you all! (early thanksgiving today for me).



By that time, I have also found a solution myself and posted here for reference. Also, @plax pointed out below.



My solution:



--Get persons that have the tag.
WITH Person_CTE AS
(
SELECT DISTINCT NameId
FROM NameTag
WHERE TagId = 3
)
-- Looking other tags for the person.
SELECT *
FROM NameTag nt
JOIN Person_CTE p ON nt.NameId = p.NameId


Another solution as @plalx has pointed out that was written very clearly:





  1. Find all NameId that have an associated TagId of 3. E.g.



    SELECT NameId
    FROM NameTag
    WHERE TagId = 3



  2. Find all tags for NameId we found in step #1.



    SELECT NameId, TagId
    FROM NameTag
    WHERE NameId IN
    (-- Solution from #1
    SELECT NameId
    FROM NameTag
    WHERE TagId = 3)











share|improve this question
























  • So you want a resultset with All names for a tag and all the tags for those names?
    – SteveB
    Nov 21 at 21:26










  • So... What are the results that you DO want?
    – Jason A. Long
    Nov 21 at 21:27










  • @SteveB: yes, I do want that.
    – Thang Nguyen
    Nov 21 at 23:08










  • @JasonA.Long: I did say in the post.
    – Thang Nguyen
    Nov 21 at 23:08













up vote
0
down vote

favorite









up vote
0
down vote

favorite











It seems pretty simple but I have not touched SQL for years. When I come back , totally stuck with this math. Let say I have 3 tables as below:



Table Name:



|NameId| Name |
|------|------|
| 1 | John |
| 2 | Doe |
| 3 | Brian|


Table Tag:



|TagId| Tag     |
|-----|---------|
| 1 | Teacher |
| 2 | Engineer|
| 3 | Employee|


Table NameTag:



|NameId|TagId|
|---- |-----|
|1 | 1 |
|2 | 2 |
|2 | 3 |
|3 | 3 |


I want to find all names along with associated tags by a tag. E.g. find names with tag Employee (TagId = 3). I expect result like this:



|NameId|TagId|
|---- |-----|
|2 | 2 |
|2 | 3 |
|3 | 3 |


How can I achieve that in a T-SQL script?



I tried with script below but it always excludes the records 1|1 and 2|2:



SELECT *
FROM NameTag
WHERE TagId = 3


Result I do not expect:



|NameId|TagId|
|---- |-----|
|2 | 3 |
|3 | 3 |




UPDATE



Looks like there are many solutions commented below as @plax, @SteveB or @picklerick and some others pointed. I have not had a chance to test all of them but they seem working for me. Thank you all! (early thanksgiving today for me).



By that time, I have also found a solution myself and posted here for reference. Also, @plax pointed out below.



My solution:



--Get persons that have the tag.
WITH Person_CTE AS
(
SELECT DISTINCT NameId
FROM NameTag
WHERE TagId = 3
)
-- Looking other tags for the person.
SELECT *
FROM NameTag nt
JOIN Person_CTE p ON nt.NameId = p.NameId


Another solution as @plalx has pointed out that was written very clearly:





  1. Find all NameId that have an associated TagId of 3. E.g.



    SELECT NameId
    FROM NameTag
    WHERE TagId = 3



  2. Find all tags for NameId we found in step #1.



    SELECT NameId, TagId
    FROM NameTag
    WHERE NameId IN
    (-- Solution from #1
    SELECT NameId
    FROM NameTag
    WHERE TagId = 3)











share|improve this question















It seems pretty simple but I have not touched SQL for years. When I come back , totally stuck with this math. Let say I have 3 tables as below:



Table Name:



|NameId| Name |
|------|------|
| 1 | John |
| 2 | Doe |
| 3 | Brian|


Table Tag:



|TagId| Tag     |
|-----|---------|
| 1 | Teacher |
| 2 | Engineer|
| 3 | Employee|


Table NameTag:



|NameId|TagId|
|---- |-----|
|1 | 1 |
|2 | 2 |
|2 | 3 |
|3 | 3 |


I want to find all names along with associated tags by a tag. E.g. find names with tag Employee (TagId = 3). I expect result like this:



|NameId|TagId|
|---- |-----|
|2 | 2 |
|2 | 3 |
|3 | 3 |


How can I achieve that in a T-SQL script?



I tried with script below but it always excludes the records 1|1 and 2|2:



SELECT *
FROM NameTag
WHERE TagId = 3


Result I do not expect:



|NameId|TagId|
|---- |-----|
|2 | 3 |
|3 | 3 |




UPDATE



Looks like there are many solutions commented below as @plax, @SteveB or @picklerick and some others pointed. I have not had a chance to test all of them but they seem working for me. Thank you all! (early thanksgiving today for me).



By that time, I have also found a solution myself and posted here for reference. Also, @plax pointed out below.



My solution:



--Get persons that have the tag.
WITH Person_CTE AS
(
SELECT DISTINCT NameId
FROM NameTag
WHERE TagId = 3
)
-- Looking other tags for the person.
SELECT *
FROM NameTag nt
JOIN Person_CTE p ON nt.NameId = p.NameId


Another solution as @plalx has pointed out that was written very clearly:





  1. Find all NameId that have an associated TagId of 3. E.g.



    SELECT NameId
    FROM NameTag
    WHERE TagId = 3



  2. Find all tags for NameId we found in step #1.



    SELECT NameId, TagId
    FROM NameTag
    WHERE NameId IN
    (-- Solution from #1
    SELECT NameId
    FROM NameTag
    WHERE TagId = 3)








sql sql-server tsql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 at 5:19









marc_s

568k12810991249




568k12810991249










asked Nov 21 at 20:58









Thang Nguyen

134




134












  • So you want a resultset with All names for a tag and all the tags for those names?
    – SteveB
    Nov 21 at 21:26










  • So... What are the results that you DO want?
    – Jason A. Long
    Nov 21 at 21:27










  • @SteveB: yes, I do want that.
    – Thang Nguyen
    Nov 21 at 23:08










  • @JasonA.Long: I did say in the post.
    – Thang Nguyen
    Nov 21 at 23:08


















  • So you want a resultset with All names for a tag and all the tags for those names?
    – SteveB
    Nov 21 at 21:26










  • So... What are the results that you DO want?
    – Jason A. Long
    Nov 21 at 21:27










  • @SteveB: yes, I do want that.
    – Thang Nguyen
    Nov 21 at 23:08










  • @JasonA.Long: I did say in the post.
    – Thang Nguyen
    Nov 21 at 23:08
















So you want a resultset with All names for a tag and all the tags for those names?
– SteveB
Nov 21 at 21:26




So you want a resultset with All names for a tag and all the tags for those names?
– SteveB
Nov 21 at 21:26












So... What are the results that you DO want?
– Jason A. Long
Nov 21 at 21:27




So... What are the results that you DO want?
– Jason A. Long
Nov 21 at 21:27












@SteveB: yes, I do want that.
– Thang Nguyen
Nov 21 at 23:08




@SteveB: yes, I do want that.
– Thang Nguyen
Nov 21 at 23:08












@JasonA.Long: I did say in the post.
– Thang Nguyen
Nov 21 at 23:08




@JasonA.Long: I did say in the post.
– Thang Nguyen
Nov 21 at 23:08












5 Answers
5






active

oldest

votes

















up vote
2
down vote



accepted










When you can't work out a query problem, first break it down into smaller problems you can solve and then merge the smaller solutions together.





  1. Find all NameId that have an associated TagId of 3. E.g.



    SELECT NameId
    FROM NameTag
    WHERE TagId = 3



  2. Find all tags for NameId we found in step #1.



    SELECT NameId, TagId
    FROM NameTag
    WHERE NameId IN (
    -- Solution from #1
    SELECT NameId
    FROM NameTag
    WHERE TagId = 3
    )



If you then run into performance issues you can start from there and try to optimize, but the expressiveness of the query is also important for maintainability.






share|improve this answer





















  • I had found a solution myself before I looked back this answer. Plus how you describe to solve the problem. Much appreciated! I also posted my solution above.
    – Thang Nguyen
    Nov 21 at 23:06










  • Great! I'm glad you had found a solution. In your solution you dont need the DISTINCT keyword in there given (NameId, TagId) pairs are unique already, so you will not have duplicate NameId with the condition WHERE TadId = 3. I had made the same mistake originally in my answer.
    – plalx
    Nov 22 at 2:18










  • Actually, there is an Id for table NameTag. I forgot to include it.
    – Thang Nguyen
    Nov 23 at 16:28












  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P
    – plalx
    Nov 23 at 16:33










  • it does need the DISTINCT keyword because NameId and TagId are not unique. Sorry to not mention that :D.
    – Thang Nguyen
    Nov 23 at 22:43


















up vote
1
down vote













Or with a correlated subquery instead of a join, just as another way to skin that cat.



SELECT
*
FROM
@NameTag AS nt
WHERE
EXISTS
(
SELECT
1
FROM
@NameTag AS n
WHERE
n.TagId = 3
AND n.NameId = nt.NameId
);


Results:



+--------+-------+
| NameId | TagId |
+--------+-------+
| 2 | 2 |
| 2 | 3 |
| 3 | 3 |
+--------+-------+





share|improve this answer





















  • This works for me as well. And yes, whenever it works, it's always good. But if I have more choices, I would prefer not choose a nested select. Just IMO. Thanks!
    – Thang Nguyen
    Nov 23 at 22:49


















up vote
1
down vote













Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid) 





share|improve this answer























  • That works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:34










  • Good, Glad to help!
    – picklerick
    Nov 22 at 6:59


















up vote
0
down vote













I think this might be what you are looking for.



DECLARE @NameTag TABLE (NameId int, TagId int)

INSERT INTO @NameTag SELECT 1, 1
INSERT INTO @NameTag SELECT 2, 2
INSERT INTO @NameTag SELECT 2, 3
INSERT INTO @NameTag SELECT 3, 3

SELECT a2.*
FROM @NameTag a1
JOIN @NameTag a2 on a1.NameId = a2.NameId
WHERE a1.TagId = 3 ;





share|improve this answer





















  • It looks like a very clever solution despite I have not fully tested yet. I will look at it.
    – Thang Nguyen
    Nov 21 at 23:25












  • @ThangNguyen It only works because any constraint on a specific single TagId is guaranteed to return unique NameIds. a1 will refer to all unique NameIds where TagId = 3 and the JOIN essentially acts as the IN clause in my answer. I prefer the IN clause given it's closer to the semantics of what we want to achieve. Furthermore the solution would return duplicates if the initial condition is changed for something like TagId IN (2, 3). Both solutions should have a similar execution plan and that's a good one as well.
    – plalx
    Nov 22 at 2:26












  • @plalx I agree that the IN is a more easily readable solution and I like that. We just try to avoid it if the results of the inner query can get rather large because we have seen performance issue with it. We usually replace it with an EXISTS query or a JOIN if possible. I really wish the more easily readable version of the query was ALWAYS the fastest query. In this example you are completely right and I should have included it as well as the EXISTS version.
    – SteveB
    Nov 23 at 17:39


















up vote
0
down vote













You can do this without a join:



select nt.*
from (select nt.*,
sum(case when tagid = 3 then 1 else 0 end) over (partition by nameid) as cnt_3
from nametag nt
) nt
where cnt_3 > 0;





share|improve this answer





















  • It seems a little bit complex but it works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:36










  • @ThangNguyen . . . I have no idea why you would think this is complex.
    – Gordon Linoff
    Nov 22 at 0:33










  • @ThangNguyen The solution adds the aggregated SUM of rows where TagId = 3, partitioned by NameId, meaning all rows with the same NameId will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner if cnt_3 would have been named include_row IMO, given it's a bit really: the count would never be greater than 1 in this scenario. It's also a very unintuitive way of solving the problem IMO. Unless it yields any performance benefits that you need I'd keep things simple.
    – plalx
    Nov 22 at 2:38










  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!
    – Thang Nguyen
    Nov 23 at 16:13











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420386%2ftsql-how-to-get-a-record-satisfies-a-condition-without-excluding-others-that-d%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























5 Answers
5






active

oldest

votes








5 Answers
5






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
2
down vote



accepted










When you can't work out a query problem, first break it down into smaller problems you can solve and then merge the smaller solutions together.





  1. Find all NameId that have an associated TagId of 3. E.g.



    SELECT NameId
    FROM NameTag
    WHERE TagId = 3



  2. Find all tags for NameId we found in step #1.



    SELECT NameId, TagId
    FROM NameTag
    WHERE NameId IN (
    -- Solution from #1
    SELECT NameId
    FROM NameTag
    WHERE TagId = 3
    )



If you then run into performance issues you can start from there and try to optimize, but the expressiveness of the query is also important for maintainability.






share|improve this answer





















  • I had found a solution myself before I looked back this answer. Plus how you describe to solve the problem. Much appreciated! I also posted my solution above.
    – Thang Nguyen
    Nov 21 at 23:06










  • Great! I'm glad you had found a solution. In your solution you dont need the DISTINCT keyword in there given (NameId, TagId) pairs are unique already, so you will not have duplicate NameId with the condition WHERE TadId = 3. I had made the same mistake originally in my answer.
    – plalx
    Nov 22 at 2:18










  • Actually, there is an Id for table NameTag. I forgot to include it.
    – Thang Nguyen
    Nov 23 at 16:28












  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P
    – plalx
    Nov 23 at 16:33










  • it does need the DISTINCT keyword because NameId and TagId are not unique. Sorry to not mention that :D.
    – Thang Nguyen
    Nov 23 at 22:43















up vote
2
down vote



accepted










When you can't work out a query problem, first break it down into smaller problems you can solve and then merge the smaller solutions together.





  1. Find all NameId that have an associated TagId of 3. E.g.



    SELECT NameId
    FROM NameTag
    WHERE TagId = 3



  2. Find all tags for NameId we found in step #1.



    SELECT NameId, TagId
    FROM NameTag
    WHERE NameId IN (
    -- Solution from #1
    SELECT NameId
    FROM NameTag
    WHERE TagId = 3
    )



If you then run into performance issues you can start from there and try to optimize, but the expressiveness of the query is also important for maintainability.






share|improve this answer





















  • I had found a solution myself before I looked back this answer. Plus how you describe to solve the problem. Much appreciated! I also posted my solution above.
    – Thang Nguyen
    Nov 21 at 23:06










  • Great! I'm glad you had found a solution. In your solution you dont need the DISTINCT keyword in there given (NameId, TagId) pairs are unique already, so you will not have duplicate NameId with the condition WHERE TadId = 3. I had made the same mistake originally in my answer.
    – plalx
    Nov 22 at 2:18










  • Actually, there is an Id for table NameTag. I forgot to include it.
    – Thang Nguyen
    Nov 23 at 16:28












  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P
    – plalx
    Nov 23 at 16:33










  • it does need the DISTINCT keyword because NameId and TagId are not unique. Sorry to not mention that :D.
    – Thang Nguyen
    Nov 23 at 22:43













up vote
2
down vote



accepted







up vote
2
down vote



accepted






When you can't work out a query problem, first break it down into smaller problems you can solve and then merge the smaller solutions together.





  1. Find all NameId that have an associated TagId of 3. E.g.



    SELECT NameId
    FROM NameTag
    WHERE TagId = 3



  2. Find all tags for NameId we found in step #1.



    SELECT NameId, TagId
    FROM NameTag
    WHERE NameId IN (
    -- Solution from #1
    SELECT NameId
    FROM NameTag
    WHERE TagId = 3
    )



If you then run into performance issues you can start from there and try to optimize, but the expressiveness of the query is also important for maintainability.






share|improve this answer












When you can't work out a query problem, first break it down into smaller problems you can solve and then merge the smaller solutions together.





  1. Find all NameId that have an associated TagId of 3. E.g.



    SELECT NameId
    FROM NameTag
    WHERE TagId = 3



  2. Find all tags for NameId we found in step #1.



    SELECT NameId, TagId
    FROM NameTag
    WHERE NameId IN (
    -- Solution from #1
    SELECT NameId
    FROM NameTag
    WHERE TagId = 3
    )



If you then run into performance issues you can start from there and try to optimize, but the expressiveness of the query is also important for maintainability.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 21:58









plalx

32.1k44770




32.1k44770












  • I had found a solution myself before I looked back this answer. Plus how you describe to solve the problem. Much appreciated! I also posted my solution above.
    – Thang Nguyen
    Nov 21 at 23:06










  • Great! I'm glad you had found a solution. In your solution you dont need the DISTINCT keyword in there given (NameId, TagId) pairs are unique already, so you will not have duplicate NameId with the condition WHERE TadId = 3. I had made the same mistake originally in my answer.
    – plalx
    Nov 22 at 2:18










  • Actually, there is an Id for table NameTag. I forgot to include it.
    – Thang Nguyen
    Nov 23 at 16:28












  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P
    – plalx
    Nov 23 at 16:33










  • it does need the DISTINCT keyword because NameId and TagId are not unique. Sorry to not mention that :D.
    – Thang Nguyen
    Nov 23 at 22:43


















  • I had found a solution myself before I looked back this answer. Plus how you describe to solve the problem. Much appreciated! I also posted my solution above.
    – Thang Nguyen
    Nov 21 at 23:06










  • Great! I'm glad you had found a solution. In your solution you dont need the DISTINCT keyword in there given (NameId, TagId) pairs are unique already, so you will not have duplicate NameId with the condition WHERE TadId = 3. I had made the same mistake originally in my answer.
    – plalx
    Nov 22 at 2:18










  • Actually, there is an Id for table NameTag. I forgot to include it.
    – Thang Nguyen
    Nov 23 at 16:28












  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P
    – plalx
    Nov 23 at 16:33










  • it does need the DISTINCT keyword because NameId and TagId are not unique. Sorry to not mention that :D.
    – Thang Nguyen
    Nov 23 at 22:43
















I had found a solution myself before I looked back this answer. Plus how you describe to solve the problem. Much appreciated! I also posted my solution above.
– Thang Nguyen
Nov 21 at 23:06




I had found a solution myself before I looked back this answer. Plus how you describe to solve the problem. Much appreciated! I also posted my solution above.
– Thang Nguyen
Nov 21 at 23:06












Great! I'm glad you had found a solution. In your solution you dont need the DISTINCT keyword in there given (NameId, TagId) pairs are unique already, so you will not have duplicate NameId with the condition WHERE TadId = 3. I had made the same mistake originally in my answer.
– plalx
Nov 22 at 2:18




Great! I'm glad you had found a solution. In your solution you dont need the DISTINCT keyword in there given (NameId, TagId) pairs are unique already, so you will not have duplicate NameId with the condition WHERE TadId = 3. I had made the same mistake originally in my answer.
– plalx
Nov 22 at 2:18












Actually, there is an Id for table NameTag. I forgot to include it.
– Thang Nguyen
Nov 23 at 16:28






Actually, there is an Id for table NameTag. I forgot to include it.
– Thang Nguyen
Nov 23 at 16:28














@ThangNguyen I'm not sure I understand how your comment relates to mine? :P
– plalx
Nov 23 at 16:33




@ThangNguyen I'm not sure I understand how your comment relates to mine? :P
– plalx
Nov 23 at 16:33












it does need the DISTINCT keyword because NameId and TagId are not unique. Sorry to not mention that :D.
– Thang Nguyen
Nov 23 at 22:43




it does need the DISTINCT keyword because NameId and TagId are not unique. Sorry to not mention that :D.
– Thang Nguyen
Nov 23 at 22:43












up vote
1
down vote













Or with a correlated subquery instead of a join, just as another way to skin that cat.



SELECT
*
FROM
@NameTag AS nt
WHERE
EXISTS
(
SELECT
1
FROM
@NameTag AS n
WHERE
n.TagId = 3
AND n.NameId = nt.NameId
);


Results:



+--------+-------+
| NameId | TagId |
+--------+-------+
| 2 | 2 |
| 2 | 3 |
| 3 | 3 |
+--------+-------+





share|improve this answer





















  • This works for me as well. And yes, whenever it works, it's always good. But if I have more choices, I would prefer not choose a nested select. Just IMO. Thanks!
    – Thang Nguyen
    Nov 23 at 22:49















up vote
1
down vote













Or with a correlated subquery instead of a join, just as another way to skin that cat.



SELECT
*
FROM
@NameTag AS nt
WHERE
EXISTS
(
SELECT
1
FROM
@NameTag AS n
WHERE
n.TagId = 3
AND n.NameId = nt.NameId
);


Results:



+--------+-------+
| NameId | TagId |
+--------+-------+
| 2 | 2 |
| 2 | 3 |
| 3 | 3 |
+--------+-------+





share|improve this answer





















  • This works for me as well. And yes, whenever it works, it's always good. But if I have more choices, I would prefer not choose a nested select. Just IMO. Thanks!
    – Thang Nguyen
    Nov 23 at 22:49













up vote
1
down vote










up vote
1
down vote









Or with a correlated subquery instead of a join, just as another way to skin that cat.



SELECT
*
FROM
@NameTag AS nt
WHERE
EXISTS
(
SELECT
1
FROM
@NameTag AS n
WHERE
n.TagId = 3
AND n.NameId = nt.NameId
);


Results:



+--------+-------+
| NameId | TagId |
+--------+-------+
| 2 | 2 |
| 2 | 3 |
| 3 | 3 |
+--------+-------+





share|improve this answer












Or with a correlated subquery instead of a join, just as another way to skin that cat.



SELECT
*
FROM
@NameTag AS nt
WHERE
EXISTS
(
SELECT
1
FROM
@NameTag AS n
WHERE
n.TagId = 3
AND n.NameId = nt.NameId
);


Results:



+--------+-------+
| NameId | TagId |
+--------+-------+
| 2 | 2 |
| 2 | 3 |
| 3 | 3 |
+--------+-------+






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 21:40









Eric Brandt

2,1101521




2,1101521












  • This works for me as well. And yes, whenever it works, it's always good. But if I have more choices, I would prefer not choose a nested select. Just IMO. Thanks!
    – Thang Nguyen
    Nov 23 at 22:49


















  • This works for me as well. And yes, whenever it works, it's always good. But if I have more choices, I would prefer not choose a nested select. Just IMO. Thanks!
    – Thang Nguyen
    Nov 23 at 22:49
















This works for me as well. And yes, whenever it works, it's always good. But if I have more choices, I would prefer not choose a nested select. Just IMO. Thanks!
– Thang Nguyen
Nov 23 at 22:49




This works for me as well. And yes, whenever it works, it's always good. But if I have more choices, I would prefer not choose a nested select. Just IMO. Thanks!
– Thang Nguyen
Nov 23 at 22:49










up vote
1
down vote













Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid) 





share|improve this answer























  • That works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:34










  • Good, Glad to help!
    – picklerick
    Nov 22 at 6:59















up vote
1
down vote













Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid) 





share|improve this answer























  • That works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:34










  • Good, Glad to help!
    – picklerick
    Nov 22 at 6:59













up vote
1
down vote










up vote
1
down vote









Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid) 





share|improve this answer














Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid) 






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 at 22:47

























answered Nov 21 at 22:37









picklerick

33318




33318












  • That works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:34










  • Good, Glad to help!
    – picklerick
    Nov 22 at 6:59


















  • That works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:34










  • Good, Glad to help!
    – picklerick
    Nov 22 at 6:59
















That works for me. Thanks!
– Thang Nguyen
Nov 21 at 23:34




That works for me. Thanks!
– Thang Nguyen
Nov 21 at 23:34












Good, Glad to help!
– picklerick
Nov 22 at 6:59




Good, Glad to help!
– picklerick
Nov 22 at 6:59










up vote
0
down vote













I think this might be what you are looking for.



DECLARE @NameTag TABLE (NameId int, TagId int)

INSERT INTO @NameTag SELECT 1, 1
INSERT INTO @NameTag SELECT 2, 2
INSERT INTO @NameTag SELECT 2, 3
INSERT INTO @NameTag SELECT 3, 3

SELECT a2.*
FROM @NameTag a1
JOIN @NameTag a2 on a1.NameId = a2.NameId
WHERE a1.TagId = 3 ;





share|improve this answer





















  • It looks like a very clever solution despite I have not fully tested yet. I will look at it.
    – Thang Nguyen
    Nov 21 at 23:25












  • @ThangNguyen It only works because any constraint on a specific single TagId is guaranteed to return unique NameIds. a1 will refer to all unique NameIds where TagId = 3 and the JOIN essentially acts as the IN clause in my answer. I prefer the IN clause given it's closer to the semantics of what we want to achieve. Furthermore the solution would return duplicates if the initial condition is changed for something like TagId IN (2, 3). Both solutions should have a similar execution plan and that's a good one as well.
    – plalx
    Nov 22 at 2:26












  • @plalx I agree that the IN is a more easily readable solution and I like that. We just try to avoid it if the results of the inner query can get rather large because we have seen performance issue with it. We usually replace it with an EXISTS query or a JOIN if possible. I really wish the more easily readable version of the query was ALWAYS the fastest query. In this example you are completely right and I should have included it as well as the EXISTS version.
    – SteveB
    Nov 23 at 17:39















up vote
0
down vote













I think this might be what you are looking for.



DECLARE @NameTag TABLE (NameId int, TagId int)

INSERT INTO @NameTag SELECT 1, 1
INSERT INTO @NameTag SELECT 2, 2
INSERT INTO @NameTag SELECT 2, 3
INSERT INTO @NameTag SELECT 3, 3

SELECT a2.*
FROM @NameTag a1
JOIN @NameTag a2 on a1.NameId = a2.NameId
WHERE a1.TagId = 3 ;





share|improve this answer





















  • It looks like a very clever solution despite I have not fully tested yet. I will look at it.
    – Thang Nguyen
    Nov 21 at 23:25












  • @ThangNguyen It only works because any constraint on a specific single TagId is guaranteed to return unique NameIds. a1 will refer to all unique NameIds where TagId = 3 and the JOIN essentially acts as the IN clause in my answer. I prefer the IN clause given it's closer to the semantics of what we want to achieve. Furthermore the solution would return duplicates if the initial condition is changed for something like TagId IN (2, 3). Both solutions should have a similar execution plan and that's a good one as well.
    – plalx
    Nov 22 at 2:26












  • @plalx I agree that the IN is a more easily readable solution and I like that. We just try to avoid it if the results of the inner query can get rather large because we have seen performance issue with it. We usually replace it with an EXISTS query or a JOIN if possible. I really wish the more easily readable version of the query was ALWAYS the fastest query. In this example you are completely right and I should have included it as well as the EXISTS version.
    – SteveB
    Nov 23 at 17:39













up vote
0
down vote










up vote
0
down vote









I think this might be what you are looking for.



DECLARE @NameTag TABLE (NameId int, TagId int)

INSERT INTO @NameTag SELECT 1, 1
INSERT INTO @NameTag SELECT 2, 2
INSERT INTO @NameTag SELECT 2, 3
INSERT INTO @NameTag SELECT 3, 3

SELECT a2.*
FROM @NameTag a1
JOIN @NameTag a2 on a1.NameId = a2.NameId
WHERE a1.TagId = 3 ;





share|improve this answer












I think this might be what you are looking for.



DECLARE @NameTag TABLE (NameId int, TagId int)

INSERT INTO @NameTag SELECT 1, 1
INSERT INTO @NameTag SELECT 2, 2
INSERT INTO @NameTag SELECT 2, 3
INSERT INTO @NameTag SELECT 3, 3

SELECT a2.*
FROM @NameTag a1
JOIN @NameTag a2 on a1.NameId = a2.NameId
WHERE a1.TagId = 3 ;






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 21:34









SteveB

551214




551214












  • It looks like a very clever solution despite I have not fully tested yet. I will look at it.
    – Thang Nguyen
    Nov 21 at 23:25












  • @ThangNguyen It only works because any constraint on a specific single TagId is guaranteed to return unique NameIds. a1 will refer to all unique NameIds where TagId = 3 and the JOIN essentially acts as the IN clause in my answer. I prefer the IN clause given it's closer to the semantics of what we want to achieve. Furthermore the solution would return duplicates if the initial condition is changed for something like TagId IN (2, 3). Both solutions should have a similar execution plan and that's a good one as well.
    – plalx
    Nov 22 at 2:26












  • @plalx I agree that the IN is a more easily readable solution and I like that. We just try to avoid it if the results of the inner query can get rather large because we have seen performance issue with it. We usually replace it with an EXISTS query or a JOIN if possible. I really wish the more easily readable version of the query was ALWAYS the fastest query. In this example you are completely right and I should have included it as well as the EXISTS version.
    – SteveB
    Nov 23 at 17:39


















  • It looks like a very clever solution despite I have not fully tested yet. I will look at it.
    – Thang Nguyen
    Nov 21 at 23:25












  • @ThangNguyen It only works because any constraint on a specific single TagId is guaranteed to return unique NameIds. a1 will refer to all unique NameIds where TagId = 3 and the JOIN essentially acts as the IN clause in my answer. I prefer the IN clause given it's closer to the semantics of what we want to achieve. Furthermore the solution would return duplicates if the initial condition is changed for something like TagId IN (2, 3). Both solutions should have a similar execution plan and that's a good one as well.
    – plalx
    Nov 22 at 2:26












  • @plalx I agree that the IN is a more easily readable solution and I like that. We just try to avoid it if the results of the inner query can get rather large because we have seen performance issue with it. We usually replace it with an EXISTS query or a JOIN if possible. I really wish the more easily readable version of the query was ALWAYS the fastest query. In this example you are completely right and I should have included it as well as the EXISTS version.
    – SteveB
    Nov 23 at 17:39
















It looks like a very clever solution despite I have not fully tested yet. I will look at it.
– Thang Nguyen
Nov 21 at 23:25






It looks like a very clever solution despite I have not fully tested yet. I will look at it.
– Thang Nguyen
Nov 21 at 23:25














@ThangNguyen It only works because any constraint on a specific single TagId is guaranteed to return unique NameIds. a1 will refer to all unique NameIds where TagId = 3 and the JOIN essentially acts as the IN clause in my answer. I prefer the IN clause given it's closer to the semantics of what we want to achieve. Furthermore the solution would return duplicates if the initial condition is changed for something like TagId IN (2, 3). Both solutions should have a similar execution plan and that's a good one as well.
– plalx
Nov 22 at 2:26






@ThangNguyen It only works because any constraint on a specific single TagId is guaranteed to return unique NameIds. a1 will refer to all unique NameIds where TagId = 3 and the JOIN essentially acts as the IN clause in my answer. I prefer the IN clause given it's closer to the semantics of what we want to achieve. Furthermore the solution would return duplicates if the initial condition is changed for something like TagId IN (2, 3). Both solutions should have a similar execution plan and that's a good one as well.
– plalx
Nov 22 at 2:26














@plalx I agree that the IN is a more easily readable solution and I like that. We just try to avoid it if the results of the inner query can get rather large because we have seen performance issue with it. We usually replace it with an EXISTS query or a JOIN if possible. I really wish the more easily readable version of the query was ALWAYS the fastest query. In this example you are completely right and I should have included it as well as the EXISTS version.
– SteveB
Nov 23 at 17:39




@plalx I agree that the IN is a more easily readable solution and I like that. We just try to avoid it if the results of the inner query can get rather large because we have seen performance issue with it. We usually replace it with an EXISTS query or a JOIN if possible. I really wish the more easily readable version of the query was ALWAYS the fastest query. In this example you are completely right and I should have included it as well as the EXISTS version.
– SteveB
Nov 23 at 17:39










up vote
0
down vote













You can do this without a join:



select nt.*
from (select nt.*,
sum(case when tagid = 3 then 1 else 0 end) over (partition by nameid) as cnt_3
from nametag nt
) nt
where cnt_3 > 0;





share|improve this answer





















  • It seems a little bit complex but it works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:36










  • @ThangNguyen . . . I have no idea why you would think this is complex.
    – Gordon Linoff
    Nov 22 at 0:33










  • @ThangNguyen The solution adds the aggregated SUM of rows where TagId = 3, partitioned by NameId, meaning all rows with the same NameId will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner if cnt_3 would have been named include_row IMO, given it's a bit really: the count would never be greater than 1 in this scenario. It's also a very unintuitive way of solving the problem IMO. Unless it yields any performance benefits that you need I'd keep things simple.
    – plalx
    Nov 22 at 2:38










  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!
    – Thang Nguyen
    Nov 23 at 16:13















up vote
0
down vote













You can do this without a join:



select nt.*
from (select nt.*,
sum(case when tagid = 3 then 1 else 0 end) over (partition by nameid) as cnt_3
from nametag nt
) nt
where cnt_3 > 0;





share|improve this answer





















  • It seems a little bit complex but it works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:36










  • @ThangNguyen . . . I have no idea why you would think this is complex.
    – Gordon Linoff
    Nov 22 at 0:33










  • @ThangNguyen The solution adds the aggregated SUM of rows where TagId = 3, partitioned by NameId, meaning all rows with the same NameId will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner if cnt_3 would have been named include_row IMO, given it's a bit really: the count would never be greater than 1 in this scenario. It's also a very unintuitive way of solving the problem IMO. Unless it yields any performance benefits that you need I'd keep things simple.
    – plalx
    Nov 22 at 2:38










  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!
    – Thang Nguyen
    Nov 23 at 16:13













up vote
0
down vote










up vote
0
down vote









You can do this without a join:



select nt.*
from (select nt.*,
sum(case when tagid = 3 then 1 else 0 end) over (partition by nameid) as cnt_3
from nametag nt
) nt
where cnt_3 > 0;





share|improve this answer












You can do this without a join:



select nt.*
from (select nt.*,
sum(case when tagid = 3 then 1 else 0 end) over (partition by nameid) as cnt_3
from nametag nt
) nt
where cnt_3 > 0;






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 22:41









Gordon Linoff

752k34286394




752k34286394












  • It seems a little bit complex but it works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:36










  • @ThangNguyen . . . I have no idea why you would think this is complex.
    – Gordon Linoff
    Nov 22 at 0:33










  • @ThangNguyen The solution adds the aggregated SUM of rows where TagId = 3, partitioned by NameId, meaning all rows with the same NameId will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner if cnt_3 would have been named include_row IMO, given it's a bit really: the count would never be greater than 1 in this scenario. It's also a very unintuitive way of solving the problem IMO. Unless it yields any performance benefits that you need I'd keep things simple.
    – plalx
    Nov 22 at 2:38










  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!
    – Thang Nguyen
    Nov 23 at 16:13


















  • It seems a little bit complex but it works for me. Thanks!
    – Thang Nguyen
    Nov 21 at 23:36










  • @ThangNguyen . . . I have no idea why you would think this is complex.
    – Gordon Linoff
    Nov 22 at 0:33










  • @ThangNguyen The solution adds the aggregated SUM of rows where TagId = 3, partitioned by NameId, meaning all rows with the same NameId will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner if cnt_3 would have been named include_row IMO, given it's a bit really: the count would never be greater than 1 in this scenario. It's also a very unintuitive way of solving the problem IMO. Unless it yields any performance benefits that you need I'd keep things simple.
    – plalx
    Nov 22 at 2:38










  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!
    – Thang Nguyen
    Nov 23 at 16:13
















It seems a little bit complex but it works for me. Thanks!
– Thang Nguyen
Nov 21 at 23:36




It seems a little bit complex but it works for me. Thanks!
– Thang Nguyen
Nov 21 at 23:36












@ThangNguyen . . . I have no idea why you would think this is complex.
– Gordon Linoff
Nov 22 at 0:33




@ThangNguyen . . . I have no idea why you would think this is complex.
– Gordon Linoff
Nov 22 at 0:33












@ThangNguyen The solution adds the aggregated SUM of rows where TagId = 3, partitioned by NameId, meaning all rows with the same NameId will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner if cnt_3 would have been named include_row IMO, given it's a bit really: the count would never be greater than 1 in this scenario. It's also a very unintuitive way of solving the problem IMO. Unless it yields any performance benefits that you need I'd keep things simple.
– plalx
Nov 22 at 2:38




@ThangNguyen The solution adds the aggregated SUM of rows where TagId = 3, partitioned by NameId, meaning all rows with the same NameId will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner if cnt_3 would have been named include_row IMO, given it's a bit really: the count would never be greater than 1 in this scenario. It's also a very unintuitive way of solving the problem IMO. Unless it yields any performance benefits that you need I'd keep things simple.
– plalx
Nov 22 at 2:38












Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!
– Thang Nguyen
Nov 23 at 16:13




Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!
– Thang Nguyen
Nov 23 at 16:13


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420386%2ftsql-how-to-get-a-record-satisfies-a-condition-without-excluding-others-that-d%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Berounka

Sphinx de Gizeh

Different font size/position of beamer's navigation symbols template's content depending on regular/plain...