2012-04-03 13 views
33

C'è un modo per ottenere una colonna in tempo reale, da una query principale, e usarla in una sottoquery?SQL Server: utilizza le colonne della query principale nella sottoquery

Qualcosa di simile a questo: (Utilizza a.Item nella subquery)

SELECT item1, * 
FROM TableA A 
INNER JOIN 
(
    select * 
    from TableB B 
    where A.item = B.item 
) on A.x = B.x; 

Ok, qui è la vera cosa:

ho bisogno di modificare questa query esistente. Ha funzionato prima, ma ora che il database è cambiato, ho bisogno di fare alcune modifiche, aggiungere alcuni confronti. Come puoi vedere ci sono un sacco di JOIN, e uno di loro è un sottoquery. Ho bisogno di aggiungere un confronto da una colonna dalla query principale (dal T0 tavolo per esempio) per la sottoquery (come questo: T6.UnionAll_Empresa = T0.UnionALl_Empresa)

Select T0.UnionAll_Empresa,<STUFF> 

from [UNION_ALL_BASES]..OINV T0 with (nolock) 
inner join [UNION_ALL_BASES]..INV6 T1 with (nolock) on t0.DocEntry = t1.DocEntry and t0.UnionAll_Empresa = t1.UnionAll_Empresa 
inner join 

(
select 
t1.CompanyID, 
T2.CompanyDb, 
t1.OurNumber, 
T6.BankCode, 
T6.BankName, 
T3.[Description] Situation, 
T1.[Status], 
T5.Descrption nomeStatus, 
T1.Origin, 
T1.DocEntry, 
T1.DocType, 
T1.ControlKey, 
T1.CardCode, 
T4.[Description] ContractBank, 
T1.PayMethodCode, 
T1.DueDate, 
T1.DocDate, 
T1.InstallmentID, 
T1.InstallmentValue, 
T1.Correction, 
T1.InterestContractural, 
T1.FineContract, 
T1.ValueAbatment, 
T1.ValueDiscount, 
T1.ValueFineLate, 
T1.ValueInterestDaysOfLate, 
T1.OtherIncreases, 
T1.ValueInWords, 
T1.ValueDocument, 
T1.DigitalLine, 
T1.Document 
from [IntegrationBank]..BillOfExchange T1 with (nolock) 
    inner join [InterCompany2]..CompanyHierarchy T2 with (nolock) on T1.CompanyID = T2.ID 
    left join [IntegrationBank]..BillOfExchangeSituation T3 with (nolock) on T1.Situation = T3.ID 
    inner join [IntegrationBank]..ContractBank T4 with (nolock) on T1.ContractBank = T4.ID 
    inner join [IntegrationBank]..BoeStatus T5 with (nolock) on T1.[Status] = T5.ID 
    inner join [UNION_ALL_BASES]..ODSC T6 with (nolock) on T4.BankKey = T6.AbsEntry and **T6.UnionAll_Empresa = T0.UnionALl_Empresa** --I need to do this 
where T1.[Status] <> 5 
and T2.CompanyDb = **T0.UnionAll_Empresa** --I need to do this 
) TBI on (T1.DocEntry = TBI.DocEntry and T1.InstlmntID = TBI.InstallmentID and TBI.DocType = T1.ObjType) 
inner join [UNION_ALL_BASES]..OCTG T2 on T0.GroupNum = T2.GroupNum and T0.UnionAll_Empresa = T2.UnionAll_Empresa 
inner join [UNION_ALL_BASES]..OSLP T3 on T0.SlpCode = T3.SlpCode and T0.UnionAll_Empresa = T3.UnionAll_Empresa 
where not exists (select 1 
     from [UNION_ALL_BASES]..RIN1 A with (nolock) 
       inner join [UNION_ALL_BASES]..ORIN B with (nolock) on A.DocEntry = B.DocEntry and A.UnionAll_Empresa = B.UnionAll_Empresa 
     where A.BaseEntry = T0.DocEntry 
     and B.SeqCode = ''1'') 
+1

puoi specificare cosa intendi per "ottenere un campo in tempo reale"? Tempo reale? Cosa significa? – ControlAltDel

+1

Non è possibile farlo perché non si tratta di una sottoquery. Questa è una tabella derivata. A seconda del tuo database potresti essere in grado di farlo. MS Sql Server ha 'cross apply/outer apply' per questo scopo. Ancora più importante, perché ne hai bisogno? Perché il join non è adatto? –

+0

Ho aggiornato la mia risposta per il vostro codice attuale. Puoi semplicemente aggiungere un'altra condizione al tuo "JOIN" ed essere fatto. – JNK

risposta

19

Non avete bisogno di una sottoquery per questo:

SELECT item1, * 
FROM TableA A 
INNER JOIN 
    TableB B 
    ON A.item = B.item 
    AND A.x = B.x; 

Non riesco a pensare a uno scenario in cui avresti bisogno di JOIN su una sottoquery con un filtro come quello in cui non sarebbe equivalente a fare semplicemente riferimento al campo direttamente nella query esterna.

È possibile fare riferimento alla tabella esterna nella sottoquery nella clausola WHERE, però:

SELECT <stuff> 
FROM Table t 
WHERE EXISTS (SELECT 1 from TableB B 
       WHERE t.id = b.id) 

EDIT

Per il vostro codice vero e proprio, basta cambiare i JOIN criteri a questo:

) TBI on (T1.DocEntry = TBI.DocEntry 
      and T1.InstlmntID = TBI.InstallmentID 
      and TBI.DocType = T1.ObjType 
      AND TBI.CompanyDB = T0.UnionAll_Empresa) 
+1

Beh, questo era solo un esempio. La vera query è un po 'complessa, e mi piacerebbe davvero un approccio come quello che ho detto, anche se dovessi usare una sorta di variabile globale o qualsiasi altra cosa =/ –

+0

@ JoãoGuilherme, ho pensato che fosse una semplificazione. Per cosa esattamente hai bisogno di questo? Le condizioni di 'JOIN' esistono per scenari come questo. – JNK

+0

potresti provare a nominare la query secondaria, ad esempio SELECT * FROM a, (SELECT * FROM WHERE a.x = y) b WHERE ... Dovresti essere in grado di fare ciò che vuoi. Potrebbe esserci un limite a quanto profondo puoi annidare se più di 3 potrebbe essere un problema. Guardando in rete è possibile per sintassi - on (A.x = B.x) – Alex

10

Se si desidera partecipare a una subquery e "ottenere una colonna in tempo reale"/riferimento a una colonna dalla query principale, poi c'è un trucco per fare questo.

Non è possibile accedere alle tabelle, che sono al di fuori della sottoquery se è usato come una tabella alias, in altre parole, questo SQL non può mai accedere A:

... 
INNER JOIN 
(
    select * 
    from TableB B 
    where A.item = B.item 
) on A.x = B.x; 

Il modo per accedere A sarebbe in questo modo:

SELECT item1, * 
FROM TableA A 
INNER JOIN TableB on TableB.item = TableA.item and TableB.item in 
(
    select top 1 B.Item 
    from TableB B 
    where A.item = B.item 
) 

semplicemente ignorare il pezzo "top 1", ho solo aggiunto che per mostrare che ci può un motivo per fare un join come questo.
Quindi, in sostanza, se si desidera fare riferimento a un elemento dalla query nella sottoquery, è sufficiente spostare la sottoquery nella sezione ON di un join e utilizzare la parola chiave IN come illustrato sopra.

+0

Questo è ciò di cui avevo bisogno. – James

+0

Mi ha aiutato con il mio problema – AdRock

31

Puoi ESTERNO utente APPLICABILE

SELECT * 
    FROM tbl1 
      OUTER APPLY (SELECT TOP 1 
            currency_id, 
            SUM(taxrate) AS taxrate 
          FROM  tbl2 
          WHERE  wuptr.currency_id = tbl1.currency_id 
          GROUP BY tbl2.currencyid 
         ) 
+0

Questa è in realtà la risposta corretta che funziona per i casi in cui l'approccio delle subquery non può essere utilizzato o non è pratico. –

9

È possibile farlo nominando le tabelle della query principale e la query nidificate. Per esempio:

SELECT continent, name, population FROM world x 
    WHERE population >= ALL 
    (SELECT population FROM world y 
     WHERE y.continent=x.continent 
      AND population>0) 

di riferimento: http://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial

+1

Riferimento alla parola chiave 'ALL' https: // msdn.microsoft.com/en-us/library/ms178543.aspx?f=255&MSPPError=-2147217396 – PedroC88

1

Non certo perché le persone sono over-complicare questo. @JNK è corretto che puoi spostare il predicato nella query principale. Per completezza, dimostrerò.

Hai due predicati nel subquery che fanno riferimento T0:

T6.UnionAll_Empresa = T0.UnionAll_Empresa 
T2.CompanyDb = T0.UnionAll_Empresa 

Il primo è un INNER JOIN predicato sul tavolo T6, e la seconda una clausola WHERE - questi sono entrambi i filtri "duri", e Will filtrare i risultati che non corrispondono (a differenza di uno LEFT OUTER JOIN che semplicemente imposta il riferimento ai valori di quella tabella su NULL).

Ebbene, dal momento T6.UnionAll_Empresa e T2.CompanyDb sia necessario filtrare contro T0.UnionAll_Empresa, allora possiamo semplicemente cambiare la INNER JOIN predicato T6 a questo:

T2.CompanyDb = T6.UnionAll_Empresa 

Poi, siamo in grado di rimuovere la clausola WHERE nel subquery, e siamo in grado di aggiungere questo JOIN predicato TBI nella query principale:

TBI.CompanyDb = T0.UnionAll_Empresa 

... rendendo l'intero Thi interrogazione s:

Select T0.UnionAll_Empresa,<STUFF> 

from [UNION_ALL_BASES]..OINV T0 with (nolock) 
inner join [UNION_ALL_BASES]..INV6 T1 with (nolock) on t0.DocEntry = t1.DocEntry and t0.UnionAll_Empresa = t1.UnionAll_Empresa 
inner join 
(
    select 
    t1.CompanyID, 
    T2.CompanyDb, 
    t1.OurNumber, 
    T6.BankCode, 
    T6.BankName, 
    T3.[Description] Situation, 
    T1.[Status], 
    T5.Descrption nomeStatus, 
    T1.Origin, 
    T1.DocEntry, 
    T1.DocType, 
    T1.ControlKey, 
    T1.CardCode, 
    T4.[Description] ContractBank, 
    T1.PayMethodCode, 
    T1.DueDate, 
    T1.DocDate, 
    T1.InstallmentID, 
    T1.InstallmentValue, 
    T1.Correction, 
    T1.InterestContractural, 
    T1.FineContract, 
    T1.ValueAbatment, 
    T1.ValueDiscount, 
    T1.ValueFineLate, 
    T1.ValueInterestDaysOfLate, 
    T1.OtherIncreases, 
    T1.ValueInWords, 
    T1.ValueDocument, 
    T1.DigitalLine, 
    T1.Document 
    from [IntegrationBank]..BillOfExchange T1 with (nolock) 
    inner join [InterCompany2]..CompanyHierarchy T2 with (nolock) on T1.CompanyID = T2.ID 
    left join [IntegrationBank]..BillOfExchangeSituation T3 with (nolock) on T1.Situation = T3.ID 
    inner join [IntegrationBank]..ContractBank T4 with (nolock) on T1.ContractBank = T4.ID 
    inner join [IntegrationBank]..BoeStatus T5 with (nolock) on T1.[Status] = T5.ID 
    inner join [UNION_ALL_BASES]..ODSC T6 with (nolock) on T4.BankKey = T6.AbsEntry and T2.CompanyDb = T6.UnionAll_Empresa 
    where T1.[Status] <> 5 
) TBI on (T1.DocEntry = TBI.DocEntry and T1.InstlmntID = TBI.InstallmentID and TBI.DocType = T1.ObjType and TBI.CompanyDb = T0.UnionAll_Empresa) 
inner join [UNION_ALL_BASES]..OCTG T2 on T0.GroupNum = T2.GroupNum and T0.UnionAll_Empresa = T2.UnionAll_Empresa 
inner join [UNION_ALL_BASES]..OSLP T3 on T0.SlpCode = T3.SlpCode and T0.UnionAll_Empresa = T3.UnionAll_Empresa 
where not exists (
    select 1 
    from [UNION_ALL_BASES]..RIN1 A with (nolock) 
    inner join [UNION_ALL_BASES]..ORIN B with (nolock) on A.DocEntry = B.DocEntry and A.UnionAll_Empresa = B.UnionAll_Empresa 
    where A.BaseEntry = T0.DocEntry 
    and B.SeqCode = ''1'' 
) 

Ciò è del tutto equivalente a quello che si ha, e rimuove ogni riferimento alla T0 dalla subquery.

Problemi correlati