2012-04-10 21 views
5

Jak mogę odwołać się do kolumny poza podzapytaniem przy użyciu Oracle? Muszę go użyć w instrukcji WHERE podzapytania.Referencyjna kolumna nadrzędnego zapytania w podzapytanie (Oracle)

Zasadniczo mam to:

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 

Chciałbym zmienić WHERE Attribute.ItemNo=12345 do WHERE Attribute.ItemNo=Item.ItemNo w podzapytania, ale nie mogę dowiedzieć się, czy jest to możliwe. Wciąż otrzymuję "ORA-00904: 'produkt' 'ItemNo'. Nieprawidłowy identyfikator"

EDIT:

Ok, to dlaczego muszę tego rodzaju konstrukcji:

chcę być w stanie uzyskać liczbę rekordów "Błąd" (gdy elementowi brakuje wartości) i zapisy "OK" (gdzie pozycja ma wartość).

Sposób, w jaki ustawiłem go w skrzypcach, zwraca poprawne dane. Myślę, że mógłbym właśnie zakończyć wypełnianie wartości w każdym z podzapytań, ponieważ prawdopodobnie byłby to najprostszy sposób. Przepraszam, jeśli moje struktury danych są trochę zawiłe. Mogę wyjaśnić, jeśli zajdzie taka potrzeba.

Moje tabele są:

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)); 

i moje zapytanie tak daleko jest:

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; 

Jest również skonfigurować w SQL Fiddle.

+0

Nie możesz .. co chcesz wybrać? może mieć inne rozwiązanie niż lewe sprzężenie zewnętrzne. – hkutluay

+0

zobacz sqlfiddle – tedski

Odpowiedz

0

Możesz to zrobić w pod-zapytaniu, ale nie w złączeniu. W twoim przypadku nie widzę potrzeby. Możesz umieścić go w warstwie łączenia.

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 

Optymalizator został skonstruowany tak, aby radzić sobie z tego rodzaju sytuacją, więc wykorzystaj go!

Zmieniono count(1) na group by, tak jak potrzebujesz group by wszystkie kolumny, które nie są agregowane.

jestem przy założeniu, że rzeczywista zapytanie jest bardziej skomplikowana, niż to jak z kolumnami jesteś Wybranie tego jest prawdopodobnie equivilent do

select itemno, group 
    from item 
where itemno = 12345 

Można również napisać sub-zapytanie o analytic function zamiast. Coś takiego jak count(*) over (partition by group).

Odłóż na bok, używając słowa kluczowego jako nazwy kolumny, w tym przypadku group jest złym pomysłem TM. Może powodować wiele zamieszania. Jak widać z powyższego kodu, masz tam dużo groups.


Tak, w oparciu o SQL-Fiddle, które dodałem do pytania myślę, że szukasz coś jak następuje, co nie wygląda dużo lepiej.Podejrzewam, że z czasem mogę to uprościć. Z drugiej strony wyraźne obniżenie zapytań o osłonę nigdy nie jest warte kłopotów, jakie powoduje. Podążyłem jednak za konwencją nazewnictwa.

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

Dzięki, przejrzę te funkcje analityczne. Masz rację, próbowałem odtworzyć przykład tak prosto, jak to możliwe. Lepszym odzwierciedleniem mojego celu końcowego jest dodanie do edycji elementu sqlfiddle. – tedski

+0

@tedski, moja odpowiedź wciąż jest ważna! Użycie mniej skomplikowanego przykładu jest standardową praktyką, ułatwia życie wszystkim. Nadal możesz umieścić swój stan w połączeniu ... – Ben

+0

Niestety, mój przykład nie uchwycił mojego problemu poprawnie. W podkwerendę jest połączona kolejna tabela i faktycznie są dwa obliczenia. Liczę, kiedy element w połączonej tabeli ma wartość zerową, a gdy nie jest. Jeśli dodałem numer pozycji, wyplułbym dwie kolumny zamiast jednej. – tedski

-4

Możesz umieścić WHERE atrybut.itemno = item.itemno wewnątrz podzapytania. Będziesz filtrować dane mimo to, filtrowanie danych w podzapytaniu jest zwykle szybsze.

+0

Nie mogę ... przeczytać ostatniego akapitu. – tedski

+0

PO stwierdził, że to nie działa w pytaniu. – Ben

Powiązane problemy