选择列中具有多个值的行,并比较不同列中的值

时间:2018-03-31 03:55:44

标签: sql database db2

我已经研究了这一点,但我无法找到我遇到的问题的答案。我有一个有四列的表,如下所示:

+------+------+------+------+
|ID    |LOAD  |STOP  |A/D/AD|
+------+------+------+------+
|1     |A     |1     |A     |
+------+------+------+------+
|2     |B     |2     |AD    |
+------+------+------+------+
|3     |C     |1     |D     |
+------+------+------+------+
|4     |A     |1     |D     |
+------+------+------+------+
|5     |D     |2     |AD    |
+------+------+------+------+
|6     |C     |2     |A     |
+------+------+------+------+
|7     |C     |2     |D     |
+------+------+------+------+
|8     |E     |1     |A     |
+------+------+------+------+
|9     |F     |2     |D     |
+------+------+------+------+
|10    |G     |1     |A     |
+------+------+------+------+

由此,我需要检索A / D / AD列中没有AD或A和D的所有加载和停止号码。为了进一步说明,我想查看每个单独的加载并查看其停止编号,然后查看表中是否有任何其他外观与这些值。然后我想查看值是什么,只返回条目,如果它在A / D / AD列中没有AD或两个条目同时具有A和D.那么我的结果应该是这样的:

+------+------+------+------+
|ID    |LOAD  |STOP  |A/D/AD|
+------+------+------+------+
|3     |C     |1     |D     |
+------+------+------+------+
|8     |E     |1     |A     |
+------+------+------+------+
|9     |F     |2     |D     |
+------+------+------+------+
|10    |G     |1     |A     |
+------+------+------+------+

因此,为了扩展结果,我们可以查看加载C并看到它出现多次,但加载C,停止1只出现一次。加载C,停止1仅在A / D / AD列中具有值D,因此返回。我尝试了多个涉及case语句的解决方案,但这似乎并不是我需要的。我已经考虑过使用工会本身,但我无法做到这一点,因为它们可能会返回不同数量的行。我完全坚持如何实现必要的逻辑来实现我的目标。任何帮助将不胜感激

1 个答案:

答案 0 :(得分:0)

有很多方法。自然或简单的方法是使用子查询检查存在(在您的情况下匹配LoadStop列)。如果你以小块的形式打破整个工作,可以使用UNION将每个块组合成最终输出。因此,第一任校长'问题的解决方法是:

select  Id, Load, Stop, A_D_AD
from    Table a
where   A_D_AD = 'A'
    and not exists (
        select  *
        from    Table d
        where   d.Load = a.Load
            and d.Stop = a.Stop
            and d.A_D_AD = 'D'
union all
select  ... 
/* Similar query for rows where A_D_AD = 'D' but 
   matches for A_D_AD = 'A' do not exist.  */

但是,在某些情况下,您可以更好地理解输入数据。例如。如果您的情况如下:

  • 任何' A'给定Load/Stop对的行
  • 从未有过' AD'行,
  • 从来没有第二个' A'行,
  • 且只有0或1' D'行。
  • 和类似的' D'给Load/Stop对的行。

然后,您可以使用简单的计数查询轻松找到要返回的Load/Stop对:

select  Load, Stop
from    Table t
where   t.A_D_AD in ('A', 'D')
group by Load, Stop
having  count(*) = 1 /* Guarantees either A without D or vice-versa*/

将这些结果连接回基表会产生所有列(在下一个示例中演示)。

最后,在一些更复杂的场景中,您可能会发现它更容易:

  • 将您的数据转化为您感兴趣的值的摘要;
  • 根据您的规则过滤;
  • 并加入回源数据

例如:

select  Id, Load, Stop, A_D_AD
from    (
        select  *
        from    (
                select  Load, Stop,
                        sum(case A_D_AD when 'A' then 1 else 0 end) as A_Count,
                        sum(case A_D_AD when 'D' then 1 else 0 end) as D_Count,
                        sum(case A_D_AD when 'AD' then 1 else 0 end) as AD_Count
                from    Table
                group by Load, Stop
                ) pvt /* Pivoted to count the rows for each A/D/AD value */

        where   pvt.AD_Count = 0
            or  (pvt.A_Count = 0 and pvt.D_Count = 0)
        ) f /* The Stop/Load rows to return */
        inner join Table src /* Join back to source data */
          on  src.Stop = f.Stop
          and src.Load = f.Load