如何清理这些Sql数据?

如何清理这些Sql数据?,sql,sql-server,Sql,Sql Server,这是一个问题的后续问题 我在一个db表中有以下数据 Name LeftId RightId ------------------------------------------ Cat 1 Cat 1 Dog 2 Dog 2 Dog 3 D

这是一个问题的后续问题

我在一个db表中有以下数据

Name                LeftId    RightId
------------------------------------------
Cat                     1  
Cat                     1
Dog                     2
Dog                     2
Dog                               3
Dog                               3
Gerbil                  4         5 
Cat                
Bird
Cow                     6
Cow
Cow                               7
Dog                     8         9
请注意,有些行没有LeftId和RightId的数据

现在,我想做的是找到两个不同的查询

  • 在两列之一中至少有一个Id的所有行,以及在这两个Id列中都没有数据的行
  • 例如

  • LeftId和RightId为NULL的所有行都按相同的名称分组。如果另一行(具有相同名称)的LeftId或RightId中有值,则不会返回此名称
  • 例如


    编辑:正确地改写了第一个问题。

    如果我理解正确,那么这就相当微不足道了:

    1:

    2:

    如果这不正确,也许你可以澄清一下

    编辑:已更新(查询1)

    问题2)


    我希望我在这里理解正确

    问题1:

    SELECT t1.Name, COALESCE(MIN(t1.LeftID), MIN(t1.RightID))
    FROM Table t1
    WHERE EXISTS(SELECT t2.Name
                 FROM Table t2
                 WHERE t2.Name = t1.Name 
                 AND   t2.LeftID IS NULL AND t2.RightID IS NULL)
    AND   COALESCE(MIN(t1.LeftID), MIN(t1.RightID)) IS NOT NULL
    GROUP BY t1.Name
    
    SELECT [Name], [LeftID], [RightID]
    
    FROM [TestTable]
    
    WHERE -- "All rows which have at least 1 Id in one of the two columns"
          ([LeftID] IS NOT NULL OR [RightID] IS NOT NULL)
          OR
          -- "Rows with NO data in both of those two Id columns"
          ([LeftID] IS NULL AND [RightID] IS NULL)
    
    问题2:

    SELECT t1.Name
    FROM Table t1
    WHERE NOT EXISTS(SELECT t2.Name
                     FROM Table t2
                     WHERE t2.Name = t1.Name
                     AND   (t2.LeftID IS NOT NULL OR t2.RightID IS NOT NULL))
    
    SELECT [Name], [LeftID], [RightID]
    
    FROM [TestTable]
    
    WHERE -- "All the rows where LeftId and RightId are NULL
          -- grouped by the same name"
          ([LeftID] IS NULL AND [RightID] IS NULL)
          AND
          -- "If another row (with the same name) has a value
          -- in the LeftId or RightId, this name will not be returned"    
          ([Name] NOT IN (SELECT DISTINCT [Name] FROM [TestTable]
                          WHERE [LeftID] IS NOT NULL
                                OR
                                [RightID] IS NOT NULL))
    
    GROUP BY [Name], [LeftID], [RightID]
    
    问题1:

    SELECT t1.Name, COALESCE(MIN(t1.LeftID), MIN(t1.RightID))
    FROM Table t1
    WHERE EXISTS(SELECT t2.Name
                 FROM Table t2
                 WHERE t2.Name = t1.Name 
                 AND   t2.LeftID IS NULL AND t2.RightID IS NULL)
    AND   COALESCE(MIN(t1.LeftID), MIN(t1.RightID)) IS NOT NULL
    GROUP BY t1.Name
    
    SELECT [Name], [LeftID], [RightID]
    
    FROM [TestTable]
    
    WHERE -- "All rows which have at least 1 Id in one of the two columns"
          ([LeftID] IS NOT NULL OR [RightID] IS NOT NULL)
          OR
          -- "Rows with NO data in both of those two Id columns"
          ([LeftID] IS NULL AND [RightID] IS NULL)
    
    问题2:

    SELECT t1.Name
    FROM Table t1
    WHERE NOT EXISTS(SELECT t2.Name
                     FROM Table t2
                     WHERE t2.Name = t1.Name
                     AND   (t2.LeftID IS NOT NULL OR t2.RightID IS NOT NULL))
    
    SELECT [Name], [LeftID], [RightID]
    
    FROM [TestTable]
    
    WHERE -- "All the rows where LeftId and RightId are NULL
          -- grouped by the same name"
          ([LeftID] IS NULL AND [RightID] IS NULL)
          AND
          -- "If another row (with the same name) has a value
          -- in the LeftId or RightId, this name will not be returned"    
          ([Name] NOT IN (SELECT DISTINCT [Name] FROM [TestTable]
                          WHERE [LeftID] IS NOT NULL
                                OR
                                [RightID] IS NOT NULL))
    
    GROUP BY [Name], [LeftID], [RightID]
    
    结果:

    Name                                               LeftID      RightID
    -------------------------------------------------- ----------- -----------
    Cat                                                1           NULL
    Cat                                                1           NULL
    Dog                                                2           NULL
    Dog                                                2           NULL
    Dog                                                NULL        3
    Dog                                                NULL        3
    Gerbil                                             4           5
    Cat                                                NULL        NULL
    Bird                                               NULL        NULL
    Cow                                                6           NULL
    Cow                                                NULL        NULL
    Cow                                                NULL        7
    Dog                                                8           9
    
    (13 row(s) affected)
    
    Name                                               LeftID      RightID
    -------------------------------------------------- ----------- -----------
    Bird                                               NULL        NULL
    
    (1 row(s) affected)
    

    对于第一个查询,您需要满足以下两个条件的行:

  • 行中的
    名称
    出现在表中的同一行中,
    LeftId
    righID
    均为空
  • 行中的
    名称
    出现在同一行的表中,其中
    左ID
    右ID
    中至少有一个不为空
  • 那么#1是通过以下方式完成的:

    SELECT Name FROM Tbl WHERE (LeftId IS NULL) AND (RightId IS NULL)
    
    SELECT Name FROM Tbl WHERE (LeftId IS NOT NULL) OR (RightId IS NOT NULL)
    
    和#2由以下人员完成:

    SELECT Name FROM Tbl WHERE (LeftId IS NULL) AND (RightId IS NULL)
    
    SELECT Name FROM Tbl WHERE (LeftId IS NOT NULL) OR (RightId IS NOT NULL)
    
    您可以将它们相交以查看两个列表中出现的
    名称
    s:

    SELECT Name FROM Tbl WHERE (LeftId IS NULL) AND (RightId IS NULL)
    INTERSECT
    SELECT Name FROM Tbl WHERE (LeftId IS NOT NULL) OR (RightId IS NOT NULL)
    
    返回:

    Name
    ----
    Cat
    Cow
    
    Name  Id
    ----  --
    Cat   1
    Cow   6
    
    Name
    ----
    Bird
    
    但是您需要
    LeftId
    righID
    ,而您不关心哪个,因此我想我们将在名称上聚合:

    SELECT Name, MIN(LeftId) AS LeftId, MIN(RightId) AS RightId 
        FROM Tbl WHERE Tbl.Name IN (
          SELECT Name FROM Tbl WHERE (LeftId IS NULL) AND (RightId IS NULL)
          INTERSECT
          SELECT Name FROM Tbl WHERE (LeftId IS NOT NULL) OR (RightId IS NOT NULL)
        )
    GROUP BY Name
    
    返回

    Name  LeftId  RightId
    ----  ------  -------
    Cat   1
    Cow   6       7
    
    已经建议使用COALESE将这两个ID转换为单个ID。那么这个呢:

    SELECT Name, COALESCE(MIN(LeftId),MIN(RightId)) AS Id 
        FROM Tbl WHERE Tbl.Name IN (
          SELECT Name FROM Tbl WHERE (LeftId IS NULL) AND (RightId IS NULL)
          INTERSECT
          SELECT Name FROM Tbl WHERE (LeftId IS NOT NULL) OR (RightId IS NOT NULL)
        )
    GROUP BY Name
    
    返回:

    Name
    ----
    Cat
    Cow
    
    Name  Id
    ----  --
    Cat   1
    Cow   6
    
    Name
    ----
    Bird
    

    对于第二个查询,您需要符合以下条件的行:

  • Name
    仅在没有
    LeftId
    righID
  • 我想不出用一组条件在SQL中实现这种自引用查询的方法,所以我将把它分解为两个条件。必须遵守这两项规定才能被接受:

  • Name
    出现在没有
    LeftId
    righID
  • Name
    不会出现在具有
    LeftId
    righID
    的行中
  • 做#1很简单:

    SELECT Name FROM Tbl WHERE (LeftId IS NULL) AND (RightId IS NULL)
    
    但是#2很棘手。当然,执行与#2相反的操作(“所有出现在具有
    LeftId
    righID
    的行中的
    Name
    )与前面一样:

    SELECT Name FROM Tbl WHERE (LeftId IS NOT NULL) OR (RightId IS NOT NULL)
    
    现在是棘手的一点-我们想要所有服从#1但不服从#2相反的行。这就是除了之外的有用的地方:

    SELECT Name FROM Tbl WHERE (LeftId IS NULL) AND (RightId IS NULL)
    EXCEPT
    SELECT Name FROM Tbl WHERE (LeftId IS NOT NULL) OR (RightId IS NOT NULL)
    
    返回:

    Name
    ----
    Cat
    Cow
    
    Name  Id
    ----  --
    Cat   1
    Cow   6
    
    Name
    ----
    Bird
    

    这正是我们想要的!

    第二个是不正确的。对于该查询,我是在所有行(按名称分组)之后,这些行(每个组)都没有Id。因此,在您的代码中,Cow有一行具有两个空值,但它也有一些其他行,其中一个字段具有数字。因此,不应返回Cow。否:(我重新编写了两个q。也许这会有帮助/澄清。第一个查询没有在sql2008中运行。您最好给出您得到的错误。“它没有运行”给我们提供了完全没有依据的信息,我们无法帮助您。但是,我想我可以猜到您需要一个GROUP by子句,因为聚合函数MIN()这就是您得到的错误。我编辑了答案,请重试。