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












0















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 '18 at 21:26











  • So... What are the results that you DO want?

    – Jason A. Long
    Nov 21 '18 at 21:27











  • @SteveB: yes, I do want that.

    – Thang Nguyen
    Nov 21 '18 at 23:08











  • @JasonA.Long: I did say in the post.

    – Thang Nguyen
    Nov 21 '18 at 23:08
















0















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 '18 at 21:26











  • So... What are the results that you DO want?

    – Jason A. Long
    Nov 21 '18 at 21:27











  • @SteveB: yes, I do want that.

    – Thang Nguyen
    Nov 21 '18 at 23:08











  • @JasonA.Long: I did say in the post.

    – Thang Nguyen
    Nov 21 '18 at 23:08














0












0








0








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 '18 at 5:19









marc_s

583k13011241270




583k13011241270










asked Nov 21 '18 at 20:58









Thang NguyenThang Nguyen

134




134













  • So you want a resultset with All names for a tag and all the tags for those names?

    – SteveB
    Nov 21 '18 at 21:26











  • So... What are the results that you DO want?

    – Jason A. Long
    Nov 21 '18 at 21:27











  • @SteveB: yes, I do want that.

    – Thang Nguyen
    Nov 21 '18 at 23:08











  • @JasonA.Long: I did say in the post.

    – Thang Nguyen
    Nov 21 '18 at 23:08



















  • So you want a resultset with All names for a tag and all the tags for those names?

    – SteveB
    Nov 21 '18 at 21:26











  • So... What are the results that you DO want?

    – Jason A. Long
    Nov 21 '18 at 21:27











  • @SteveB: yes, I do want that.

    – Thang Nguyen
    Nov 21 '18 at 23:08











  • @JasonA.Long: I did say in the post.

    – Thang Nguyen
    Nov 21 '18 at 23:08

















So you want a resultset with All names for a tag and all the tags for those names?

– SteveB
Nov 21 '18 at 21:26





So you want a resultset with All names for a tag and all the tags for those names?

– SteveB
Nov 21 '18 at 21:26













So... What are the results that you DO want?

– Jason A. Long
Nov 21 '18 at 21:27





So... What are the results that you DO want?

– Jason A. Long
Nov 21 '18 at 21:27













@SteveB: yes, I do want that.

– Thang Nguyen
Nov 21 '18 at 23:08





@SteveB: yes, I do want that.

– Thang Nguyen
Nov 21 '18 at 23:08













@JasonA.Long: I did say in the post.

– Thang Nguyen
Nov 21 '18 at 23:08





@JasonA.Long: I did say in the post.

– Thang Nguyen
Nov 21 '18 at 23:08












5 Answers
5






active

oldest

votes


















2














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 '18 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 '18 at 2:18











  • Actually, there is an Id for table NameTag. I forgot to include it.

    – Thang Nguyen
    Nov 23 '18 at 16:28













  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P

    – plalx
    Nov 23 '18 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 '18 at 22:43



















1














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 '18 at 22:49



















1














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 '18 at 23:34











  • Good, Glad to help!

    – picklerick
    Nov 22 '18 at 6:59



















0














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 '18 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 '18 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 '18 at 17:39



















0














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 '18 at 23:36











  • @ThangNguyen . . . I have no idea why you would think this is complex.

    – Gordon Linoff
    Nov 22 '18 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 '18 at 2:38











  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!

    – Thang Nguyen
    Nov 23 '18 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',
autoActivateHeartbeat: false,
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









2














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 '18 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 '18 at 2:18











  • Actually, there is an Id for table NameTag. I forgot to include it.

    – Thang Nguyen
    Nov 23 '18 at 16:28













  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P

    – plalx
    Nov 23 '18 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 '18 at 22:43
















2














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 '18 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 '18 at 2:18











  • Actually, there is an Id for table NameTag. I forgot to include it.

    – Thang Nguyen
    Nov 23 '18 at 16:28













  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P

    – plalx
    Nov 23 '18 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 '18 at 22:43














2












2








2







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 '18 at 21:58









plalxplalx

33.3k44770




33.3k44770













  • 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 '18 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 '18 at 2:18











  • Actually, there is an Id for table NameTag. I forgot to include it.

    – Thang Nguyen
    Nov 23 '18 at 16:28













  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P

    – plalx
    Nov 23 '18 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 '18 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 '18 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 '18 at 2:18











  • Actually, there is an Id for table NameTag. I forgot to include it.

    – Thang Nguyen
    Nov 23 '18 at 16:28













  • @ThangNguyen I'm not sure I understand how your comment relates to mine? :P

    – plalx
    Nov 23 '18 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 '18 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 '18 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 '18 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 '18 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 '18 at 2:18













Actually, there is an Id for table NameTag. I forgot to include it.

– Thang Nguyen
Nov 23 '18 at 16:28







Actually, there is an Id for table NameTag. I forgot to include it.

– Thang Nguyen
Nov 23 '18 at 16:28















@ThangNguyen I'm not sure I understand how your comment relates to mine? :P

– plalx
Nov 23 '18 at 16:33





@ThangNguyen I'm not sure I understand how your comment relates to mine? :P

– plalx
Nov 23 '18 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 '18 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 '18 at 22:43













1














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 '18 at 22:49
















1














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 '18 at 22:49














1












1








1







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 '18 at 21:40









Eric BrandtEric Brandt

3,02511127




3,02511127













  • 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 '18 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 '18 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 '18 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 '18 at 22:49











1














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 '18 at 23:34











  • Good, Glad to help!

    – picklerick
    Nov 22 '18 at 6:59
















1














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 '18 at 23:34











  • Good, Glad to help!

    – picklerick
    Nov 22 '18 at 6:59














1












1








1







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 '18 at 22:47

























answered Nov 21 '18 at 22:37









picklerickpicklerick

32918




32918













  • That works for me. Thanks!

    – Thang Nguyen
    Nov 21 '18 at 23:34











  • Good, Glad to help!

    – picklerick
    Nov 22 '18 at 6:59



















  • That works for me. Thanks!

    – Thang Nguyen
    Nov 21 '18 at 23:34











  • Good, Glad to help!

    – picklerick
    Nov 22 '18 at 6:59

















That works for me. Thanks!

– Thang Nguyen
Nov 21 '18 at 23:34





That works for me. Thanks!

– Thang Nguyen
Nov 21 '18 at 23:34













Good, Glad to help!

– picklerick
Nov 22 '18 at 6:59





Good, Glad to help!

– picklerick
Nov 22 '18 at 6:59











0














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 '18 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 '18 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 '18 at 17:39
















0














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 '18 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 '18 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 '18 at 17:39














0












0








0







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 '18 at 21:34









SteveBSteveB

639315




639315













  • It looks like a very clever solution despite I have not fully tested yet. I will look at it.

    – Thang Nguyen
    Nov 21 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 at 17:39











0














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 '18 at 23:36











  • @ThangNguyen . . . I have no idea why you would think this is complex.

    – Gordon Linoff
    Nov 22 '18 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 '18 at 2:38











  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!

    – Thang Nguyen
    Nov 23 '18 at 16:13
















0














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 '18 at 23:36











  • @ThangNguyen . . . I have no idea why you would think this is complex.

    – Gordon Linoff
    Nov 22 '18 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 '18 at 2:38











  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!

    – Thang Nguyen
    Nov 23 '18 at 16:13














0












0








0







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 '18 at 22:41









Gordon LinoffGordon Linoff

791k35315419




791k35315419













  • It seems a little bit complex but it works for me. Thanks!

    – Thang Nguyen
    Nov 21 '18 at 23:36











  • @ThangNguyen . . . I have no idea why you would think this is complex.

    – Gordon Linoff
    Nov 22 '18 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 '18 at 2:38











  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!

    – Thang Nguyen
    Nov 23 '18 at 16:13



















  • It seems a little bit complex but it works for me. Thanks!

    – Thang Nguyen
    Nov 21 '18 at 23:36











  • @ThangNguyen . . . I have no idea why you would think this is complex.

    – Gordon Linoff
    Nov 22 '18 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 '18 at 2:38











  • Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!

    – Thang Nguyen
    Nov 23 '18 at 16:13

















It seems a little bit complex but it works for me. Thanks!

– Thang Nguyen
Nov 21 '18 at 23:36





It seems a little bit complex but it works for me. Thanks!

– Thang Nguyen
Nov 21 '18 at 23:36













@ThangNguyen . . . I have no idea why you would think this is complex.

– Gordon Linoff
Nov 22 '18 at 0:33





@ThangNguyen . . . I have no idea why you would think this is complex.

– Gordon Linoff
Nov 22 '18 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 '18 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 '18 at 2:38













Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!

– Thang Nguyen
Nov 23 '18 at 16:13





Thanks for explaining, plalx. @Gordon: honestly I have just had an overlook but it's working. Thanks!

– Thang Nguyen
Nov 23 '18 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.




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

Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

ComboBox Display Member on multiple fields

Is it possible to collect Nectar points via Trainline?