【问题标题】:Select distinct not-null rows SQL server 2005选择不同的非空行 SQL Server 2005
【发布时间】:2010-12-04 09:43:48
【问题描述】:

我遇到了以下问题。
我有一张这样的桌子:

ID   ID1     ID2     ID3     ID4     ID5
1   NULL    NULL    NULL    NULL    1
2   NULL    NULL    NULL    2       NULL
3   NULL    NULL    NULL    2       1
4   3       NULL    NULL    2       NULL
5   3       NULL    NULL    2       1
6   NULL    5       NULL    2       NULL

我需要得到不同的行,它认为 NULL 等于任何值。对于这个例子,答案是:

ID   ID1     ID2     ID3     ID4     ID5
5   3       NULL    NULL    2       1
6   NULL    5       NULL    2       NULL

附:这里 ID 是主键,因此是唯一的。 ID1-ID5 - 任何整数。
提前致谢! 更新
说 null 等于任何数字我的意思是它被任何数字吸收

【问题讨论】:

  • 您的示例答案并没有真正遵循模式。
  • @rwilliams - 问题很好,理解它被提及 - NULL CAN TAKE ANY VALUES...
  • 最好说null被任意数吸收
  • @StuffHappens:您能否解释一下原因为什么这两行是预期结果?
  • 我们以第 1 行和第 3 行为例。它们的 ID5 相同,ID4 的唯一区别是第 3 行有一个数字,而第 1 行有空值。至于数字 absorbs null 我们得出结论,这些行的操作结果是第 3 行。依此类推。假设第 5 行吸收了第 3 行,因为它们的 ID4 和 ID5 相等,但第 5 行具有 id1 的数字值,而第 3 行没有。

标签: sql sql-server-2005 select distinct


【解决方案1】:

这个可行,不知道能不能再简单点

SELECT ID1, ID2, ID3, ID4, ID5
FROM IDS OUTT
WHERE NOT EXISTS (SELECT 1
                FROM IDS INN
                WHERE OUTT.ID != INN.ID AND
                      (ISNULL(OUTT.ID1, INN.ID1) = INN.ID1 OR (INN.ID1 IS NULL AND OUTT.ID1 IS NULL)) AND
                      (ISNULL(OUTT.ID2, INN.ID2) = INN.ID2 OR (INN.ID2 IS NULL AND OUTT.ID2 IS NULL)) AND
                      (ISNULL(OUTT.ID3, INN.ID3) = INN.ID3 OR (INN.ID3 IS NULL AND OUTT.ID3 IS NULL)) AND
                      (ISNULL(OUTT.ID4, INN.ID4) = INN.ID4 OR (INN.ID4 IS NULL AND OUTT.ID4 IS NULL)) AND
                      (ISNULL(OUTT.ID5, INN.ID5) = INN.ID5 OR (INN.ID5 IS NULL AND OUTT.ID5 IS NULL)))

编辑:如果您的 id 永远不会有负数,找到一个更甜蜜的选择

SELECT ID1, ID2, ID3, ID4, ID5
FROM IDS OUTT
WHERE NOT EXISTS (SELECT 1
                FROM IDS INN
                WHERE OUTT.ID != INN.ID AND
                      coalesce(OUTT.ID1, INN.ID1,-1) = isnull(INN.ID1,-1) AND
                      coalesce(OUTT.ID2, INN.ID2,-1) = isnull(INN.ID2,-1) AND
                      coalesce(OUTT.ID3, INN.ID3,-1) = isnull(INN.ID3,-1) AND
                      coalesce(OUTT.ID4, INN.ID4,-1) = isnull(INN.ID4,-1) AND
                      coalesce(OUTT.ID5, INN.ID5,-1) = isnull(INN.ID5,-1))  

EDIT2:在一种情况下它不起作用 - 如果两行(具有不同的 id)具有完全相同的形式。我假设它不存在。如果存在这种情况,则首先在基表上创建一个带有 select distinct 的视图,然后应用此查询。

【讨论】:

  • 什么.. 没有赞成,没有接受如此辛勤工作的答案?我想我必须高兴才能解决一个棘手的问题!
  • @Martin - 我已经用给出的样本数据检查了这一点。它肯定有效。如果你愿意,你可以试试。
  • @Martin - 它返回那些没有具有较小空值的替代形式的行。这意味着返回所有其他行
  • 真是天才。我试图解决这个问题,考虑采取哪些行,但您的方法是基于不采取哪些行。它看起来很棒。
【解决方案2】:

据我了解您的问题陈述:

您从完整的表格开始:

ID   ID1     ID2     ID3     ID4     ID5
1   NULL    NULL    NULL    NULL    1
2   NULL    NULL    NULL    2       NULL
3   NULL    NULL    NULL    2       1
4   3       NULL    NULL    2       NULL
5   3       NULL    NULL    2       1
6   NULL    5       NULL    2       NULL

然后您消除“重复”行,即。具有较少但与其他行相同的值的行(NULL 除外 - 并且不包括 ID 列):

  • 第 1 行被消除,因为第 3 行相同,但在第 1 行有NULL 的地方有更多值。

  • 第 2 行同样被第 2 行或第 4 行消除。

  • 第 3 行和第 4 行被第 5 行淘汰。

然后剩下第 5 行和第 6 行:

ID   ID1     ID2     ID3     ID4     ID5
5   3       NULL    NULL    2       1
6   NULL    5       NULL    2       NULL

我的回答:

坦率地说,我不知道如何使用 SQL 的 SELECT DISTINCT 或更一般地使用 SQL 的基于集合的逻辑来完成此操作。我可以想象,您可以使用更程序化的方法(例如使用光标)进行这种过滤——但我无法为此提供解决方案。


关于术语的说明:

NULL 等于任何值

NULL 从不等于任何值,因为 NULL 本身不是一个值;这是没有价值。 NULL 本质上意味着“未知”。 (NULL 不是一个值的事实是你不应该写IDx = NULL 而是IDx IS NULL 的原因。)

【讨论】:

  • 看来你做对了。我在这个问题的标题中提到了 distinct,因为这个操作类似于 distinct。但是解决方案可能与 distinct 无关。
  • 第 2 行被第 3 行淘汰。
【解决方案3】:

如果 ID1, ID2 (...) 始终具有相同的值,就像在您的示例中一样,您可以这样做

Select 
 SUM(id1)/COUNT(id1),
 SUM(id2)/COUNT(id2),
 SUM(id3)/COUNT(id3),
 SUM(id4)/COUNT(id4),
 SUM(id5)/COUNT(id5)  From TABLE

函数 SUM 和 COUNT 将忽略该空值。 但是你的问题仍然有点困惑.. :)

【讨论】:

  • 它们不需要相同的值。不好的例子 =)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-15
  • 1970-01-01
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 2013-07-08
相关资源
最近更新 更多