如何清理这个Sql数据?

时间:2009-05-15 04:57:14

标签: sql sql-server

这是previously asked question的后续问题。

我在一个数据库表中有以下数据。

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,某些行没有数据。

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

  1. 在两个列中的一列中至少有1个Id的所有行和这两个Id列中没有数据的行。
  2. 例如

    Cat     1
    Cow     6 (or 7 .. i'm not worried)
    
    1. LeftId和RightId为NULL的所有行按相同名称分组。如果另一行(具有相同名称)在LeftId或RightId中具有值,则不会返回此名称。
    2. 例如

      Bird
      

      HMM ..

      编辑:正确地重新提出第一个问题。

5 个答案:

答案 0 :(得分:2)

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

  1. 行中的Name出现在LeftIdRightId都为NULL的同一行的表格中。
  2. 行中的Name出现在同一行的表格中,LeftIdRightId中至少有一个为空。
  3. 嗯,#1由:

    完成
    SELECT Name FROM Tbl WHERE (LeftId IS NULL) AND (RightId IS NULL)
    

    #2由:

    完成
    SELECT Name FROM Tbl WHERE (LeftId IS NOT NULL) OR (RightId IS NOT NULL)
    

    你可以相交,看看哪个Name出现在两个列表中:

    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
    

    但是你想要LeftIdRightId,而你不关心哪个,所以我想我们会在名称上聚合:

    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
    

    lc已建议使用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  Id
    ----  --
    Cat   1
    Cow   6
    

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

    1. Name仅出现在没有LeftIdRightId
    2. 的行中

      我想不出在一组标准中在SQL中进行那种自引用查询的方法,所以我将其分解为两个标准。必须遵守两者才能被接受:

      1. Name显示在没有LeftIdRightId
      2. 的行中
      3. Name not 会出现在LeftIdRightId
      4. 的行中

        做#1只是:

        SELECT Name FROM Tbl WHERE (LeftId IS NULL) AND (RightId IS NULL)
        

        但#2很棘手。当然,与#2相反(“NameLeftId行中出现的所有RightId都与之前相同:

        SELECT Name FROM Tbl WHERE (LeftId IS NOT NULL) OR (RightId IS NOT NULL)
        

        现在是棘手的一点 - 我们希望所有符合#1的行但不遵守#2的相反行。这是 EXCEPT 有用的地方:

        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
        ----
        Bird
        

        这就是我们想要的!

答案 1 :(得分:0)

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

1:

SELECT * 
FROM your_table 
WHERE (LeftId IS NOT NULL 
AND RightId IS NULL)
OR
(LeftId IS NULL 
AND RightId IS NOT NULL)

2:

SELECT * 
FROM your_table
WHERE 
    NOT EXISTS 
              (SELECT * FROM your_table y1
               WHERE (y1.LeftId IS NOT NULL OR y1.RightId IS NOT NULL)
               AND y1.name = your_table.name)

如果这不对,那么也许你可以澄清一下。

修改:已更新

答案 2 :(得分:0)

查询1)

SELECT * 
FROM Table 
WHERE (LeftID IS NULL AND RightID IS NOT NULL) 
    OR (LeftID IS NOT NULL AND RightID IS NULL)

查询2)

SELECT * 
FROM Table 
WHERE LeftID IS NULL AND RightID IS NULL

答案 3 :(得分:0)

我希望我能在这里正确理解你。

查询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

查询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))

答案 4 :(得分:0)

查询1:

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 [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)
相关问题