2012-04-10 27 views
5

Làm cách nào để tham chiếu cột bên ngoài truy vấn phụ bằng Oracle? Tôi đặc biệt cần sử dụng nó trong câu lệnh WHERE của truy vấn phụ.Cột truy vấn cha tham chiếu trong truy vấn phụ (Oracle)

Về cơ bản tôi có điều này:

SELECT Item.ItemNo, Item.Group 
FROM Item 
    LEFT OUTER JOIN (SELECT Attribute.Group, COUNT(1) CT 
        FROM Attribute 
        WHERE Attribute.ItemNo=12345) A ON A.Group = Item.Group 
WHERE Item.ItemNo=12345 

Tôi muốn thay đổi WHERE Attribute.ItemNo=12345 để WHERE Attribute.ItemNo=Item.ItemNo trong subquery, nhưng tôi không thể tìm ra nếu điều này là có thể. Tôi tiếp tục nhận được "ORA-00.904: 'mục' 'ItemNo':. Không hợp lệ Identifier"

EDIT:

Ok, đây là lý do tại sao tôi cần phải loại cấu trúc:

Tôi muốn có thể nhận được tổng số bản ghi "Lỗi" (trong đó mục thiếu giá trị) và bản ghi "OK" (trong đó mục có giá trị).

Cách tôi đã thiết lập trong fiddle trả về dữ liệu chính xác. Tôi nghĩ rằng tôi có thể chỉ cần điền vào giá trị trong mỗi truy vấn phụ, vì điều này có lẽ sẽ là cách dễ nhất. Xin lỗi nếu cấu trúc dữ liệu của tôi hơi phức tạp. Tôi có thể giải thích nếu cần thiết.

bảng của tôi là:

create table itemcountry(
    itemno number, 
    country nchar(3), 
    imgroup varchar2(10), 
    imtariff varchar2(20), 
    exgroup varchar2(10), 
    extariff varchar2(20)); 

create table itemattribute(
    attributeid varchar2(10), 
    tariffgroup varchar2(10), 
    tariffno varchar2(10)); 

create table icav(
    itemno number, 
    attributeid varchar2(10), 
    value varchar2(10)); 

và truy vấn của tôi cho đến nay là:

select itemno, country, imgroup, imtariff, im.error "imerror", im.ok "imok", exgroup, extariff, ex.error "exerror", ex.ok "exok" 
from itemcountry 
    left outer join (select sum(case when icav.itemno is null then 1 else 0 end) error, sum(case when icav.itemno is not null then 1 else 0 end) ok, tariffgroup, tariffno 
        from itemattribute ia 
        left outer join icav on ia.attributeid=icav.attributeid 
        where (icav.itemno=12345 or icav.itemno is null) 
        group by tariffgroup, tariffno) im on im.tariffgroup=imgroup and imtariff=im.tariffno 
    left outer join (select sum(case when icav.itemno is null then 1 else 0 end) error, sum(case when icav.itemno is not null then 1 else 0 end) ok, tariffgroup, tariffno 
        from itemattribute ia 
        left outer join icav on ia.attributeid=icav.attributeid 
        where (icav.itemno=12345 or icav.itemno is null) 
        group by tariffgroup, tariffno) ex on ex.tariffgroup=exgroup and extariff=ex.tariffno 
where itemno=12345; 

Nó cũng đã được thiết lập trong một SQL Fiddle.

+0

bạn không thể .. bạn muốn chọn gì? có thể có một giải pháp khác ngoài tham gia bên ngoài bên trái. – hkutluay

+0

xem sqlfiddle – tedski

Trả lời

0

Bạn có thể làm điều đó trong truy vấn phụ nhưng không thể tham gia. Trong trường hợp của bạn, tôi không thấy cần phải làm gì. Bạn có thể đặt nó trong điều kiện kết nối.

select i.itemno, i.group 
    from item i 
    left outer join (select group, itemno 
         from attribute b 
        group by group itemno) a 
    on a.group = i.group 
    and i.itemno = a.itemno 
where i.itemno = 12345 

Trình tối ưu hóa được tạo để xử lý loại tình huống này để sử dụng!

Tôi đã thay đổi count(1) thành group by khi bạn cần group by tất cả các cột không được tổng hợp.

Tôi giả định rằng truy vấn thực tế của bạn là phức tạp hơn như đối với cột mà bạn đang chọn này có lẽ equivilent để

select itemno, group 
    from item 
where itemno = 12345 

Bạn cũng có thể viết tiểu truy vấn của bạn với một analytic function để thay thế. Một cái gì đó như count(*) over (partition by group).

Để sử dụng từ khóa làm tên cột, trong trường hợp này group là ý tưởng không tốt TM. Nó có thể gây ra rất nhiều sự nhầm lẫn. Như bạn có thể thấy từ mã ở trên, bạn có rất nhiều groups trong đó.


Vì vậy, dựa trên SQL-Fiddle, mà tôi đã thêm vào câu hỏi tôi nghĩ bạn đang tìm kiếm nội dung như sau, trông không đẹp hơn nhiều.Tôi nghi ngờ, cho thời gian, tôi có thể làm cho nó đơn giản hơn. Ở một khía cạnh khác, các truy vấn vỏ bọc thấp hơn một cách rõ ràng không bao giờ đáng để gây rắc rối. Tôi đã theo quy ước đặt tên của bạn mặc dù.

with sub_query as (
select count(*) - count(icav.itemno) as error 
     , count(icav.itemno) as ok 
     , min(itemno) over() as itemno 
     , tariffgroup 
     , tariffno 
    from itemattribute ia 
    left outer join icav 
    on ia.attributeid = icav.attributeid 
    group by icav.itemno 
     , tariffgroup 
     , tariffno 
) 
    select ic.itemno, ic.country, ic.imgroup, ic.imtariff 
     , sum(im.error) as "imerror", sum(im.ok) as "imok" 
     , ic.exgroup, ic.extariff 
     , sum(ex.error) as "exerror", sum(ex.ok) as "exok" 
     from itemcountry ic 
     left outer join sub_query im 
     on ic.imgroup = im.tariffgroup 
     and ic.imtariff = im.tariffno 
     and ic.itemno = im.itemno 
     left outer join sub_query ex 
     on ic.exgroup = ex.tariffgroup 
     and ic.extariff = ex.tariffno 
     and ic.itemno = ex.itemno 
    where ic.itemno = 12345 
    group by ic.itemno, ic.country 
      , ic.imgroup, ic.imtariff 
      , ic.exgroup, ic.extariff 
      ; 
+0

Cảm ơn, tôi sẽ xem xét các chức năng phân tích đó. Bạn nói đúng, tôi đã cố gắng tạo lại ví dụ đơn giản nhất có thể. Một đại diện tốt hơn về mục tiêu cuối cùng của tôi là trong sqlfiddle tôi đã thêm vào trong bản chỉnh sửa. – tedski

+0

@tedski, câu trả lời của tôi vẫn đứng vững! Sử dụng một ví dụ ít phức tạp hơn là thực hành tiêu chuẩn, nó làm cho cuộc sống dễ dàng hơn cho tất cả mọi người. Bạn vẫn có thể đặt tình trạng của bạn trong tham gia ... – Ben

+0

Xin lỗi, ví dụ của tôi đã không nắm bắt được vấn đề của tôi một cách chính xác. Có một bảng khác đang được tham gia vào truy vấn phụ và thực sự có hai lần đếm. Tôi có một số khi mục trong bảng tham gia là null và khi nó không phải là. Nếu tôi thêm số mục vào, nó sẽ nhổ ra hai cột thay vì một cột. – tedski

-4

Bạn có thể đặt WHERE attribute.itemno = item.itemno bên trong truy vấn phụ. Bạn sẽ lọc dữ liệu, lọc dữ liệu bên trong truy vấn con thường nhanh hơn.

+0

Tôi không thể ... đọc đoạn cuối. – tedski

+0

OP đã chỉ ra rằng điều này không hoạt động trong câu hỏi. – Ben

Các vấn đề liên quan