TSQL - How to get a record satisfies a condition without excluding others that do not
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:
Find all NameId that have an associated TagId of 3. E.g.
SELECT NameId
FROM NameTag
WHERE TagId = 3
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
add a comment |
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:
Find all NameId that have an associated TagId of 3. E.g.
SELECT NameId
FROM NameTag
WHERE TagId = 3
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
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
add a comment |
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:
Find all NameId that have an associated TagId of 3. E.g.
SELECT NameId
FROM NameTag
WHERE TagId = 3
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
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:
Find all NameId that have an associated TagId of 3. E.g.
SELECT NameId
FROM NameTag
WHERE TagId = 3
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
sql sql-server tsql
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
add a comment |
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
add a comment |
5 Answers
5
active
oldest
votes
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.
Find all
NameId
that have an associatedTagId
of3
. E.g.
SELECT NameId
FROM NameTag
WHERE TagId = 3
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.
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 duplicateNameId
with the conditionWHERE 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
|
show 1 more comment
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 |
+--------+-------+
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
add a comment |
Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid)
That works for me. Thanks!
– Thang Nguyen
Nov 21 '18 at 23:34
Good, Glad to help!
– picklerick
Nov 22 '18 at 6:59
add a comment |
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 ;
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 singleTagId
is guaranteed to return uniqueNameId
s.a1
will refer to all uniqueNameId
s whereTagId = 3
and theJOIN
essentially acts as theIN
clause in my answer. I prefer theIN
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 likeTagId 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
add a comment |
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;
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 whereTagId = 3
, partitioned byNameId
, meaning all rows with the sameNameId
will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner ifcnt_3
would have been namedinclude_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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Find all
NameId
that have an associatedTagId
of3
. E.g.
SELECT NameId
FROM NameTag
WHERE TagId = 3
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.
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 duplicateNameId
with the conditionWHERE 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
|
show 1 more comment
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.
Find all
NameId
that have an associatedTagId
of3
. E.g.
SELECT NameId
FROM NameTag
WHERE TagId = 3
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.
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 duplicateNameId
with the conditionWHERE 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
|
show 1 more comment
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.
Find all
NameId
that have an associatedTagId
of3
. E.g.
SELECT NameId
FROM NameTag
WHERE TagId = 3
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.
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.
Find all
NameId
that have an associatedTagId
of3
. E.g.
SELECT NameId
FROM NameTag
WHERE TagId = 3
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.
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 duplicateNameId
with the conditionWHERE 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
|
show 1 more comment
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 duplicateNameId
with the conditionWHERE 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
|
show 1 more comment
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 |
+--------+-------+
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
add a comment |
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 |
+--------+-------+
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
add a comment |
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 |
+--------+-------+
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 |
+--------+-------+
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
add a comment |
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
add a comment |
Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid)
That works for me. Thanks!
– Thang Nguyen
Nov 21 '18 at 23:34
Good, Glad to help!
– picklerick
Nov 22 '18 at 6:59
add a comment |
Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid)
That works for me. Thanks!
– Thang Nguyen
Nov 21 '18 at 23:34
Good, Glad to help!
– picklerick
Nov 22 '18 at 6:59
add a comment |
Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid)
Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid)
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
add a comment |
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
add a comment |
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 ;
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 singleTagId
is guaranteed to return uniqueNameId
s.a1
will refer to all uniqueNameId
s whereTagId = 3
and theJOIN
essentially acts as theIN
clause in my answer. I prefer theIN
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 likeTagId 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
add a comment |
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 ;
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 singleTagId
is guaranteed to return uniqueNameId
s.a1
will refer to all uniqueNameId
s whereTagId = 3
and theJOIN
essentially acts as theIN
clause in my answer. I prefer theIN
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 likeTagId 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
add a comment |
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 ;
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 ;
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 singleTagId
is guaranteed to return uniqueNameId
s.a1
will refer to all uniqueNameId
s whereTagId = 3
and theJOIN
essentially acts as theIN
clause in my answer. I prefer theIN
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 likeTagId 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
add a comment |
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 singleTagId
is guaranteed to return uniqueNameId
s.a1
will refer to all uniqueNameId
s whereTagId = 3
and theJOIN
essentially acts as theIN
clause in my answer. I prefer theIN
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 likeTagId 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 NameId
s. a1
will refer to all unique NameId
s 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 NameId
s. a1
will refer to all unique NameId
s 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
add a comment |
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;
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 whereTagId = 3
, partitioned byNameId
, meaning all rows with the sameNameId
will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner ifcnt_3
would have been namedinclude_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
add a comment |
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;
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 whereTagId = 3
, partitioned byNameId
, meaning all rows with the sameNameId
will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner ifcnt_3
would have been namedinclude_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
add a comment |
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;
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;
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 whereTagId = 3
, partitioned byNameId
, meaning all rows with the sameNameId
will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner ifcnt_3
would have been namedinclude_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
add a comment |
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 whereTagId = 3
, partitioned byNameId
, meaning all rows with the sameNameId
will end up with the same SUM. It then only keeps the rows where the SUM is > 0. It could have been cleaner ifcnt_3
would have been namedinclude_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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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