2012-04-03 38 views
33

Có cách nào để nhận cột trong thời gian thực, từ truy vấn chính và sử dụng nó trong truy vấn phụ không?Máy chủ SQL - sử dụng các cột từ truy vấn chính trong truy vấn con

Cái gì đó như thế này: (Sử dụng A.item trong subquery)

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

Ok, đây là điều thực:

Tôi cần phải sửa đổi truy vấn hiện nay. Nó đã làm việc trước đây, nhưng bây giờ cơ sở dữ liệu đã thay đổi, tôi cần phải thực hiện một số sửa đổi, thêm một số so sánh. Như bạn có thể thấy có rất nhiều JOINS, và một trong số chúng là một truy vấn phụ. Tôi cần thêm một sự so sánh từ một cột từ truy vấn chính (từ T0 bảng ví dụ) để subquery (như thế này: 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

bạn có thể chỉ định ý nghĩa của từ "nhận một trường trong thời gian thực" không? Thời gian thực? Điều đó nghĩa là gì? – ControlAltDel

+1

Bạn không thể làm điều này vì đây không phải là truy vấn phụ. Đây là bảng có nguồn gốc. Tùy thuộc vào cơ sở dữ liệu của bạn, bạn có thể làm điều đó. MS Sql Server có 'cross apply/outer apply' cho mục đích này. Quan trọng hơn, tại sao bạn cần nó? Tại sao tham gia không phù hợp? –

+0

Tôi đã cập nhật câu trả lời cho mã thực của mình. Bạn chỉ có thể thêm một điều kiện khác vào 'JOIN' của bạn và được thực hiện. – JNK

Trả lời

19

Bạn không cần một subquery cho rằng:

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

Tôi không thể nghĩ ra một kịch bản mà bạn sẽ cần JOIN trên truy vấn con với bộ lọc như vậy, nơi nó sẽ không tương đương với chỉ tham chiếu trường trực tiếp trong truy vấn bên ngoài.

Bạn có thể tham khảo bảng bên ngoài trong subquery trong mệnh đề WHERE, mặc dù:

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

EDIT

Đối với mã thực tế của bạn, chỉ cần thay đổi JOIN tiêu chí sau:

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

Vâng, đây chỉ là một ví dụ. Truy vấn thực sự là một phức tạp nhỏ, và tôi thực sự muốn một cách tiếp cận giống như tôi đã nói, ngay cả khi tôi phải sử dụng một số biến toàn cầu hoặc bất cứ điều gì =/ –

+0

@ JoãoGuilherme Tôi cho rằng đó là một sự đơn giản hóa. Chính xác thì bạn cần cái này để làm gì? Các điều kiện 'JOIN' tồn tại cho các tình huống như thế này. – JNK

+0

bạn có thể thử đặt tên truy vấn phụ tức là SELECT * FROM a, (SELECT * FROM WHERE a.x = y) b WHERE ... Bạn sẽ có thể làm những gì bạn muốn. Có thể có giới hạn về mức độ sâu mà bạn có thể lồng nếu có hơn 3 vấn đề có thể là vấn đề. Tìm kiếm trên mạng có thể bằng cú pháp (A.x = B.x) – Alex

10

Nếu bạn muốn tham gia vào một subquery và "có được một cột trong thời gian thực"/tham khảo một cột từ truy vấn chính, sau đó là một thủ thuật để làm điều này.

Bạn không thể truy cập vào bảng đó nằm ngoài subquery nếu nó được sử dụng như một bảng aliased, nói cách khác, SQL này không bao giờ có thể truy cập A:

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

Cách để truy cập A sẽ được như thế này:

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 
) 

Chỉ cần bỏ qua phần "trên cùng 1", tôi vừa thêm điều đó để cho thấy rằng có thể có lý do để tham gia như thế này. Vì vậy, về cơ bản, nếu bạn muốn tham chiếu một mục từ truy vấn trong truy vấn phụ, chỉ cần di chuyển truy vấn phụ đến phần BẬT của một kết nối và sử dụng từ khóa IN như minh họa ở trên.

+0

Đây là những gì tôi cần. – James

+0

Giúp tôi giải quyết vấn đề của mình – AdRock

31

Bạn có thể sử dụng OUTER ÁP DỤNG

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

Đây thực sự là câu trả lời đúng cho các trường hợp không thể sử dụng phương pháp tiếp cận phụ hoặc không thực tế. –

9

Bạn có thể làm điều này bằng cách đặt tên các bảng của truy vấn chính và truy vấn lồng nhau. Ví dụ:

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

tham khảo: http://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial

+1

Tham chiếu trên từ khóa 'ALL' https: // msdn.microsoft.com/en-us/library/ms178543.aspx?f=255&MSPPError=-2147217396 – PedroC88

1

Không chắc lý do tại sao mọi người đang quá phức tạp này. @JNK đúng là bạn có thể di chuyển vị từ vào truy vấn chính. Để hoàn thành, tôi sẽ chứng minh.

Bạn có hai vị từ trong subquery của bạn mà tham khảo T0:

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

Đầu tiên là một INNER JOIN vị trên bàn T6, và lần thứ hai một khoản WHERE - đây đều là những bộ lọc "cứng", và sẽ lọc ra các kết quả không khớp (không giống như LEFT OUTER JOIN sẽ chỉ đặt tham chiếu đến các giá trị của bảng đó thành NULL).

Vâng, kể từ T6.UnionAll_EmpresaT2.CompanyDb cả cần phải lọc chống T0.UnionAll_Empresa, sau đó chúng ta có thể chỉ cần thay đổi INNER JOIN vị trên T6 này:

T2.CompanyDb = T6.UnionAll_Empresa 

Sau đó, chúng ta có thể loại bỏ các khoản WHERE trong subquery, và chúng ta có thể thêm JOIN ngữ này để TBI trong truy vấn chính:

TBI.CompanyDb = T0.UnionAll_Empresa 

... làm cho toàn bộ thi truy vấn 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'' 
) 

Điều này hoàn toàn tương đương với những gì bạn có và xóa mọi tham chiếu đến T0 khỏi truy vấn con của bạn.

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