根据单个列选择不同的结果,而不选择分组

时间:2016-01-05 19:18:50

标签: sql sql-server

我有以下数据(小提琴 - http://sqlfiddle.com/#!6/9eecb7db59d16c80417c72d1/3757):

SELECT * FROM 
(
  SELECT 1 AS Id1, 1000 AS Id2, NULL AS Item1, 1 AS Item2 --this should be removed from my results
  UNION SELECT 1 AS Id1, 1000 AS Id2, NULL AS Item1, 2 AS Item2
  UNION SELECT 3 AS Id1, 1000 AS Id2, 0 AS Item1, 0 AS Item2
  UNION SELECT 4 AS Id1, 1000 AS Id2, 1 AS Item1, 1 AS Item2

  --BELOW DATA DIFFERS FROM THE ABOVE ONLY ON Id2
  UNION SELECT 1 AS Id1, 2000 AS Id2, NULL AS Item1, 1 AS Item2 --this should be removed from my results
  UNION SELECT 1 AS Id1, 2000 AS Id2, NULL AS Item1, 2 AS Item2
  UNION SELECT 3 AS Id1, 2000 AS Id2, 0 AS Item1, 0 AS Item2
  UNION SELECT 4 AS Id1, 2000 AS Id2, 1 AS Item1, 1 AS Item2
) AS TestData

我需要过滤TestData,才能获得不同的Id1, Id2。结果必须符合以下规则:

  1. 以下所有规则都必须遵循Id2上的分组(我的意思是以下仅适用于由Id2列定义的行组)。这意味着TestData数据集包含两个组 - 1000,2000
  2. Item1匹配Item2的所有行都很好,并且始终返回
  3. 如果未达到2.,则只有当Item1NULL并且Item2 TestData(规则1.仍然适用 - 因此我们需要按当前组查看数据集)
  4. 总结一下,我需要从TestData获取每组第一行旁边的所有ID。此外,请注意我知道我可以简单地拨打SELECT DISTINCT并拥有正确的ID,但这不是这种情况。我的问题比我上面描述的要大,基本上我想知道的是,如果Item2已经在它的组中已经匹配,如何从上面提供的数据中删除每个组的第一行(规则3)。

1 个答案:

答案 0 :(得分:2)

这将返回您期望的行。 COALESCE是一种快捷方式,因此如果数据中存在负值,则您需要将查询的这些部分展开以考虑NULL值。如果其他列允许NULL值,您可能还需要添加其他检查。

SELECT
    T1.id1,
    T1.id2,
    T1.item1,
    T1.item2
FROM
    My_Table T1
WHERE
    COALESCE(T1.item1, -1) = COALESCE(T1.item2, -1) OR
    (
        T1.item1 IS NULL AND
        NOT EXISTS
        (
            SELECT *
            FROM
                My_Table T2
            WHERE
                T2.id2 = T1.id2 AND
                COALESCE(T2.item1, -1) <> COALESCE(T1.item1, -1) AND
                T2.item2 = T1.item2
        )
    )
ORDER BY
    T1.id2,
    T1.id1