通过考虑重复项来比较同一个表中的两列

时间:2016-05-31 11:51:56

标签: sql database plsql oracle11g oracle-sqldeveloper

我有一个样本表如下。

A      B               C         D
------+---------+--------+---------
3.2   |  India  |  456   |  3.2
3.2   |  India  |  -67   |  5
-3.2  |  US     |  -30   |  8
3.2   |  UK     |  3.9   |  5
5     |  UAE    |  2.4   |  9
6     |  UAE    |  5     |  -3.2

我想首先按以下格式对数据进行排序。 'B'& 'C'列与'D'列相关联,这样当我排序'D'然后'B'和' 'C'列将相应移动。 但'A'是独立的

A(ascending)   B           C       D((Descending))
------------+-----------+--------+--------
-3.2        |   UAE     |   2.4  |  9
3.2         |   US      |  -30   |  8
3.2         |   India   |  -67   |  5
3.2         |   UK      |  3.9   |  5
5           |   India   |  456   |  3.2
6           |   UAE     |  5     |  -3.2

对于上表,我想得到以下作为最终输出(我在比较时忽略了这些标志)。 在上表中,我检查'A'列(一对一映射)中的'D'列值,如果它不是它们那么它应该将其推下

A(ascending)   B           C       D((Descending))
------------+-----------+--------+--------
-3.2        |   India   |  456   |  3.2
3.2         |   UAE     |  5     |  -3.2
3.2         |   null    |  null  |  null
3.2         |   null    |  null  |  null
5           |   India   |  -67   |  5
6           |   null    |  null  |  null 
null        |   UAE     |   2.4  |  9
null        |   US      |  -30   |  8
null        |   UK      |  3.9   |  5

最终输出(按下的值):

null        |   UAE     |   2.4  |  9
null        |   US      |  -30   |  8
null        |   UK      |  3.9   |  5

它可能正在使用NOT INCOUNTJOIN,但我似乎无法正确地将它放在一起(特别是因为我从同一个表中选择数据)。有没有人对此有所了解?感谢。

1 个答案:

答案 0 :(得分:1)

以下是完全猜测,因为您的问题中没有足够的信息来完全理解您期望的a和d列之间的联接。我已经对此做了最好的猜测,但如果以下内容不正确,您必须根据您的逻辑对其进行修改,或者使用正确的逻辑更新您的问题。

with sample_data as (select 3.2 a, 'India' b, 456 c, 3.2 d from dual union all
                     select 3.2 a, 'India' b, -67 c, 5 d from dual union all
                     select -3.2 a, 'US' b, -30 c, 8 d from dual union all
                     select 3.2 a, 'UK' b, 3.9 c, 5 d from dual union all
                     select 5 a, 'UAE' b, 2.4 c, 9 d from dual union all
                     select 6 a, 'UAE' b, 5 c, -3.2 d from dual),
-- end of the "sample_data" subquery mimicking your table with data in it
             sd1 as (select row_number() over (order by a) rn,
                            a
                     from   sample_data),
             sd2 as (select row_number() over (order by d desc, b, c) rn,
                            b,
                            c,
                            d
                     from   sample_data),
             sd3 as (select sd1.a,
                            sd2.b,
                            sd2.c,
                            sd2.d
                     from   sd1
                            inner join sd2 on (sd1.rn = sd2.rn))
select case when sd5.a is not null and sd4.a is not null then sd4.a
            when sd5.a is not null then null
            else sd4.a
       end a,
       case when sd5.b is not null and row_number() over (partition by sd5.a, sd5.b, sd5.c, sd5.d order by sd4.d desc) = 1 then sd5.b
            else null
       end b,
       case when sd5.c is not null and row_number() over (partition by sd5.a, sd5.b, sd5.c, sd5.d order by sd4.d desc) = 1 then sd5.c
            else null
       end c,
       case when sd5.d is not null and row_number() over (partition by sd5.a, sd5.b, sd5.c, sd5.d order by sd4.d desc) = 1 then sd5.d
            else null
       end d
from   sd3 sd4
       full outer join sd3 sd5 on (sd4.a = sd5.d)
order by case when a is not null then 1 else 2 end,
         a;

         A B              C          D
---------- ----- ---------- ----------
      -3.2 UAE            5       -3.2
       3.2 India        456        3.2
       3.2                            
       3.2                            
         5 UK           3.9          5
         5 India        -67          5
         6                            
           UAE          2.4          9
           US           -30          8

在您提供的其他信息之后,如下所示:

with sample_data as (select 3.2 a, 'India' b, 456 c, 3.2 d from dual union all
                     select 3.2 a, 'India' b, -67 c, 5 d from dual union all
                     select -3.2 a, 'US' b, -30 c, 8 d from dual union all
                     select 3.2 a, 'UK' b, 3.9 c, 5 d from dual union all
                     select 5 a, 'UAE' b, 2.4 c, 9 d from dual union all
                     select 6 a, 'UAE' b, 5 c, -3.2 d from dual),
-- end of the "sample_data" subquery mimicking your table with data in it
             sd1 as (select row_number() over (order by a) rn,
                            a
                     from   sample_data),
             sd2 as (select row_number() over (order by d desc, b, c) rn,
                            b,
                            c,
                            d
                     from   sample_data),
             sd3 as (select sd1.a,
                            sd2.b,
                            sd2.c,
                            sd2.d,
                            row_number() over (partition by sd2.d order by sd1.a) rnd,
                            row_number() over (partition by sd1.a order by sd2.d) rna
                     from   sd1
                            inner join sd2 on (sd1.rn = sd2.rn))
select case when sd5.a is not null and sd4.a is not null then sd4.a
            when sd5.a is not null then null
            else sd4.a
       end a,
       case when sd5.b is not null then sd5.b
            else null
       end b,
       case when sd5.c is not null then sd5.c
            else null
       end c,
       case when sd5.d is not null then sd5.d
            else null
       end d
from   sd3 sd4
       full outer join sd3 sd5 on (sd4.a = sd5.d and sd4.rna = sd5.rnd)
order by case when a is not null then 1 else 2 end,
         a,
         d;

         A B              C          D
---------- ----- ---------- ----------
      -3.2 UAE            5       -3.2
       3.2 India        456        3.2
       3.2                            
       3.2                            
         5 India        -67          5
         6                            
           UK           3.9          5
           US           -30          8
           UAE          2.4          9

根据您是否真的不关心a和d列中值的符号,您可能希望在上述查询的所有相关位置使用abs()

此外,将值存储在与该行的其余部分无关的列中通常表示设计不良。为什么你的数据存储起来了?