Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TSQL-如何获取满足条件的记录,而不排除其他不满足条件的记录_Sql_Sql Server_Tsql - Fatal编程技术网

TSQL-如何获取满足条件的记录,而不排除其他不满足条件的记录

TSQL-如何获取满足条件的记录,而不排除其他不满足条件的记录,sql,sql-server,tsql,Sql,Sql Server,Tsql,这看起来很简单,但我已经多年没有接触过SQL了。当我回来的时候,我完全沉浸在数学中。假设我有3张表,如下所示: 表名: |NameId| Name | |------|------| | 1 | John | | 2 | Doe | | 3 | Brian| 表格标签: |TagId| Tag | |-----|---------| | 1 | Teacher | | 2 | Engineer| | 3 | Employee| 表名称标签: |Name

这看起来很简单,但我已经多年没有接触过SQL了。当我回来的时候,我完全沉浸在数学中。假设我有3张表,如下所示:

表名:

|NameId| Name |
|------|------|
| 1    | John |
| 2    | Doe  |
| 3    | Brian|
表格标签:

|TagId| Tag     |
|-----|---------|
| 1   | Teacher |
| 2   | Engineer|
| 3   | Employee|
表名称标签:

|NameId|TagId|
|----  |-----|
|1     | 1   |
|2     | 2   |
|2     | 3   |
|3     | 3   |
我想通过标记查找所有名称以及相关标记。例如,用标记Employee(TagId=3)查找姓名我期望这样的结果:

|NameId|TagId|
|----  |-----|    
|2     | 2   |
|2     | 3   |
|3     | 3   |
--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
如何在T-SQL脚本中实现这一点

我尝试使用下面的脚本,但它总是排除记录1 | 1和2 | 2:

SELECT *
FROM NameTag    
WHERE TagId = 3
结果我不期望:

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

更新

看起来有许多解决方案在下面被评论为@plax、@stevenb或@picklerick等。我还没有机会测试所有这些,但它们似乎对我有用。谢谢大家!!(对我来说,今天的感恩节很早)

到那时,我自己也找到了一个解决方案,并张贴在这里供参考。还有,@plax在下面指出

我的解决方案:

|NameId|TagId|
|----  |-----|    
|2     | 2   |
|2     | 3   |
|3     | 3   |
--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
@plalx指出的另一个解决方案写得非常清楚:

  • 查找关联TagId为3的所有NameId。例如

    SELECT NameId
    FROM NameTag
    WHERE TagId = 3
    
  • 查找步骤#1中找到的NameId的所有标记


  • 我想这可能就是你要找的

    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 ;
    

    我想这可能就是你要找的

    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 ;
    

    或者使用相关子查询而不是联接,就像剥猫皮的另一种方法一样

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

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

    或者使用相关子查询而不是联接,就像剥猫皮的另一种方法一样

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

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

    当你不能解决一个查询问题时,首先把它分解成你能解决的小问题,然后把小问题合并在一起

  • 查找所有与
    3
    TagId
    关联的
    NameId
    。例如

    SELECT NameId
    FROM NameTag
    WHERE TagId = 3
    
  • 查找我们在步骤1中找到的
    NameId
    的所有标记


  • 如果您随后遇到性能问题,您可以从那里开始并尝试优化,但查询的表达能力对于可维护性也很重要。

    当您无法解决查询问题时,首先将其分解为可以解决的较小问题,然后将较小的解决方案合并在一起

    Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid) 
    
  • 查找所有与
    3
    TagId
    关联的
    NameId
    。例如

    SELECT NameId
    FROM NameTag
    WHERE TagId = 3
    
  • 查找我们在步骤1中找到的
    NameId
    的所有标记


  • 如果您随后遇到性能问题,您可以从那里开始并尝试优化,但查询的表达能力对于可维护性也很重要。

    您可以在不加入
    的情况下执行此操作:

    Select * from nametag where nameid in(Select nameid from nametag where tagid=3 Group by nameid) 
    
    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;
    

    无需加入
    即可执行此操作:

    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;
    


    那么你想要一个结果集,其中包含一个标记的所有名称以及这些名称的所有标记?那么。。。你想要的结果是什么?@SteveB:是的,我想要。@JasonA.Long:我在帖子里说了。那么你想要一个包含所有标签名和所有标签名的结果集?那么。。。你想要的结果是什么?@SteveB:是的,我想要。@JasonA.Long:我在帖子中说过。在我回过头来看这个答案之前,我自己已经找到了解决方案。加上你如何描述解决问题。非常感谢!我也在上面发布了我的解决方案。太好了!我很高兴你找到了解决办法。在您的解决方案中,给定的
    (NameId,TagId)
    对已经是唯一的,因此您不需要重复的
    NameId
    ,条件是
    其中TadId=3
    。我在最初的回答中犯了同样的错误。实际上,表名标签有一个Id。我忘了把它包括在内。@thangguyen我不确定我是否理解你的评论和我的有什么关系?:Pit确实需要DISTINCT关键字,因为NameId和TagId不是唯一的。很抱歉没有提到:D.在我回顾这个答案之前,我自己已经找到了一个解决方案。加上你如何描述解决问题。非常感谢!我也在上面发布了我的解决方案。太好了!我很高兴你找到了解决办法。在您的解决方案中,给定的
    (NameId,TagId)
    对已经是唯一的,因此您不需要重复的
    NameId
    ,条件是
    其中TadId=3
    。我在最初的回答中犯了同样的错误。实际上,表名标签有一个Id。我忘了把它包括在内。@thangguyen我不确定我是否理解你的评论和我的有什么关系?:Pit确实需要DISTINCT关键字,因为NameId和TagId不是唯一的。很抱歉没有提到:D。尽管我还没有完全测试,但它看起来是一个非常聪明的解决方案。我会看看它。@ThangNguyen它之所以有效,是因为对特定单个
    TagId
    的任何约束都保证返回唯一的
    NameId
    s
    a1
    将引用所有唯一的
    NameId
    s,其中
    TagId=3
    JOIN
    基本上充当我答案中的
    IN
    子句。我更喜欢
    中的
    子句,因为它更接近我们想要实现的语义。此外,如果初始条件更改为(2,3)
    中的
    TagId,则解决方案将返回重复项。两个解决方案都应该有一个类似的执行计划,这也是一个好的计划。@plalx我同意IN是一个更容易阅读的解决方案,我喜欢它。如果内部查询的结果会变得相当大,我们只是试图避免它,因为我们已经看到了它的性能问题。如果可能的话,我们通常用EXISTS查询或JOIN替换它。我真的希望更容易阅读的查询版本总是最快的查询。在这个例子中,你是完全正确的,我应该包括它以及现有的版本。它看起来像一个非常聪明的解决方案,尽管我还没有完全测试。我会看看它。@ThangNguyen它之所以有效,是因为对特定单个
    TagId
    的任何约束都保证返回唯一的
    NameId
    s<代码>a1