2012-04-10 14 views
5

Come riferimento a una colonna esterna a una sottoquery utilizzando Oracle? Ho specificamente bisogno di usarlo nell'istruzione WHERE della sottoquery.Colonna della query padre di riferimento in subquery (Oracle)

Fondamentalmente ho questo:

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 

vorrei cambiare WHERE Attribute.ItemNo=12345 al WHERE Attribute.ItemNo=Item.ItemNo nella subquery, ma io non riesco a capire se questo è possibile. Continuo a ricevere "ORA-00904: 'Articolo' 'ITEMNO':. Valido Identifier"

EDIT:

Ok, questo è il motivo per cui ho bisogno di questo tipo di struttura:

voglio essere in grado di ottenere un conteggio dei record "Errore" (in cui all'elemento manca un valore) e dei record "OK" (dove l'articolo ha un valore).

Il modo in cui l'ho impostato nel violino restituisce i dati corretti. Penso che potrei finire col riempire il valore in ciascuna subquery, poiché questo sarebbe probabilmente il modo più semplice. Scusa se le mie strutture di dati sono un po 'contorte. Posso spiegare se necessario.

mie tabelle sono:

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

e la mia domanda finora è:

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; 

E 'anche istituito in un SQL Fiddle.

+0

non si può .. cosa si desidera selezionare? potrebbe avere un'altra soluzione oltre al join esterno sinistro. – hkutluay

+0

vedere lo sqlfiddle – tedski

risposta

0

È possibile farlo in una sottoquery ma non in un join. Nel tuo caso non vedo alcun bisogno di Puoi metterlo nella condizione di join.

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 

L'ottimizzatore è progettato per gestire questo tipo di situazione, quindi utilizzalo!

Ho modificato il count(1) in un group by come necessario a group by tutte le colonne che non sono aggregate.

sto supponendo che la query reale è più complicato di così come con le colonne che si sta selezionando questo è probabilmente equivilent a

select itemno, group 
    from item 
where itemno = 12345 

Si potrebbe anche scrivere il sub-query con una analytic function invece. Qualcosa come count(*) over (partition by group).

Come una parte utilizzando una parola chiave come nome di colonna, in questo caso group è una cattiva idea TM. Può causare molta confusione. Come puoi vedere dal codice qui sopra hai un sacco di groups lì.


Quindi, sulla base di SQL-Fiddle, che ho aggiunto alla domanda penso che siete alla ricerca di qualcosa di simile a quanto segue, che non sembra molto migliore.Sospetto che, dato il tempo, potrei renderlo più semplice. Da un'altra parte, le domande esplicitamente più basse di casing non valgono mai la seccatura che provoca. Ho seguito la tua convenzione di denominazione.

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

Grazie, esaminerò quelle funzioni analitiche. Hai ragione, stavo cercando di ricreare l'esempio il più semplicemente possibile. Una migliore rappresentazione del mio obiettivo finale è nel sqlfiddle che ho aggiunto nella modifica. – tedski

+0

@tedski, la mia risposta è ancora valida! Usare un esempio meno complicato è una pratica standard, rende la vita più facile a tutti. Puoi ancora mettere le tue condizioni nel join ... – Ben

+0

Spiacente, il mio esempio non ha catturato correttamente il mio problema. C'è un altro tavolo che si unisce alla subquery e ci sono in realtà due conteggi. Ho un conteggio di quando l'elemento nella tabella unita è nullo e quando non lo è. Se aggiungessi il numero dell'articolo, sputerebbe due colonne invece di una. – tedski

-4

È possibile inserire WHERE attribute.itemno = item.itemno all'interno della sottoquery. Stai per filtrare i dati in ogni caso, anche il filtraggio dei dati all'interno della sottoquery è di solito più veloce.

+0

Non riesco a ... leggere l'ultimo paragrafo. – tedski

+0

L'OP ha indicato che questo non funziona nella domanda. – Ben

Problemi correlati