在Oracle中将表连接到自身

时间:2015-02-19 16:49:43

标签: oracle join

非常困惑。

我试图加入一张桌子。我有以下详细信息:

PRODUCT NO           FORMAT NO             FORMAT CODE              NUMBER
1000                 1111                  P                        0
1000                 1112                  O                        0
1000                 1113                  H                        546

我想创建一个SELECT语句,输出所有" O"格式代码,而不是输出" 0"在" NUMBER"专栏,我想输出" 546"。它看起来像这样:

PRODUCT NO           FORMAT NO             FORMAT CODE              NUMBER
1000                 1112                  O                        546

所以我觉得我在这里有效地加入了这个桌子?只是不确定如何做到这一点...

谢谢!

4 个答案:

答案 0 :(得分:3)

始终保持简单,使用所有可用的Oracle内置功能。<​​/ p>

SELECT * FROM
(     
 SELECT FORMAT_NO, FORMAT_CODE, SEQ
  , (CASE WHEN FORMAT_CODE = 'O' THEN LAG(seq, 1, 0) OVER (ORDER BY FORMAT_CODE) END) nn_seq
FROM 
(                           
SELECT 1000 PRODUCT_NO, 1111 FORMAT_NO, 'P' FORMAT_CODE, 0 SEQ FROM dual
UNION
SELECT 1000, 1112, 'O', 0 FROM dual
UNION
SELECT 1000, 1113, 'H', 546 FROM dual
)
ORDER BY 2
)
WHERE FORMAT_CODE = 'O'

/

输出:     1112 O 0 546

在上面的查询中,您需要先执行排序,然后根据顺序和所需的输出使用内置LAG()或LEAD()的Oracle。

答案 1 :(得分:3)

从评论中看来,只有在O值为零时才想使用H值:

select t1.product_no, t1.format_no, t1.format_code,
  case when t1.value = 0 then t2.value else t1.value end as value
from your_table t1
join your_table t2
on t2.product_no = t1.product_no
where t1.format_code = 'O'
and t2.format_code = 'H';

PRODUCT_NO  FORMAT_NO FORMAT_CODE      VALUE
---------- ---------- ----------- ----------
      1000       1112 O                  546 

如果你可以识别格式代码或格式数字的连贯排序,你也可以使用超前/滞后而不是自我连接。如果将内部查询限制为仅两个代码O和H,则滞后很简单:

select product_no, format_no, format_code, value,
  lag(value) over (partition by product_no order by format_code) as next_code
from your_table
where format_code in ('O', 'H');

PRODUCT_NO  FORMAT_NO FORMAT_CODE      VALUE  NEXT_CODE
---------- ---------- ----------- ---------- ----------
      1000       1113 H                  546            
      1000       1112 O                    0        546 

然后您可以将其用作内部查询,再次使用coalesce(或者如果您愿意,可以解码)替换零值,并丢弃H行:

select product_no, format_no, format_code,
  case when value = 0 then next_value else value end as value
from (
  select product_no, format_no, format_code, value,
    lag(value) over (partition by product_no order by format_code) as next_value
  from your_table
  where format_code in ('O', 'H')
)
where format_code = 'O';

PRODUCT_NO  FORMAT_NO FORMAT_CODE      VALUE
---------- ---------- ----------- ----------
      1000       1112 O                  546 

这可能看起来更复杂,但它只会碰到一次。

SQL Fiddle

答案 2 :(得分:2)

我认为从上面所说的你想要这样的东西:

SELECT p1.product_no, p1.format_no, p1.format_code, p2.h_number
  FROM myproducts p1 INNER JOIN myproducts p2
    ON p1.product_no = p2.product_no
   AND p1.format_code <> p2.format_code
   AND p2.format_code = 'H'
 WHERE p1.format_code = 'O';

我必须在编辑上添加,我认为这个设计有点奇怪,我不确定是否可以称之为&#34;标准化。&#34;

答案 3 :(得分:0)

这似乎可以为您提供您想要的数据,但我怀疑它在一般情况下有效:

SELECT "PRODUCT NO", "FORMAT NO", "FORMAT CODE", MAX(NUMBER) AS NUMBER
FROM T
WHERE "FORMAT CODE" = 'O'
GROUP BY "PRODUCT NO", "FORMAT NO", "FORMAT CODE"

根据您分享的细微信息,我可能也会猜到这一点。但我仍然怀疑这是错的:

SELECT "PRODUCT NO", "FORMAT NO", "FORMAT CODE",
    CASE WHEN NUMBER <> 0 THEN NUMBER ELSE (SELECT MAX(NUMBER) FROM T) END AS NUMBER
FROM T
WHERE "FORMAT CODE" = 'O'

或者这个:

SELECT "PRODUCT NO", "FORMAT NO", "FORMAT CODE",
    CASE
        WHEN NUMBER <> 0 THEN NUMBER
        ELSE
            (
            SELECT NUMBER FROM T as t2
            WHERE
                    t2."PRODUCT NO" = t1."PRODUCT NO"
                AND t2."FORMAT CODE" = 'H'
            )
    END AS NUMBER
FROM T as t1
WHERE "FORMAT CODE" = 'O'