Periksa apakah ada nilai-nilai dalam hasil subquery

8

Saya memiliki subquery rumit yang mengembalikan daftar ID pesanan. Saya perlu mendapatkan daftar pelanggan yang memiliki pesanan ini. Masalahnya adalah bahwa ada dua cara menetapkan pelanggan ke pesanan (salah satu dari dua bidang). Saya bisa melakukan hal-hal seperti ini:

 select *
 from Customers
 where orderId in (select...) 
 or secondaryOrderId in (select ...)

Masalahnya adalah bahwa subquery sangat besar, baik dalam waktu yang dibutuhkan untuk mengeksekusi, dan dalam ruang layar yang dibutuhkan. Apakah ada cara untuk memeriksa apakah salah satu bidang berisi salah satu hasil yang diinginkan?

pengguna63844
sumber

Jawaban:

10

Mencoba:

where exists (select * .... 
        where Customers.orderId = ... 
        or Customers.secondaryId = ...
     )

Misalnya, jika Anda berencana:

where orderId in (select value from ...)
or secondaryorderid in (select value from ...)

Kemudian Anda membuatnya sehingga Anda hanya memanggil subquery Anda sekali, dan membangun klausa ATAU Anda ke dalamnya.

 where exists (select * from ... 
        where Customers.orderId = value 
        or Customers.secondaryOrderId = value
     )

Inti dari ini adalah untuk memastikan bahwa subquery yang rumit hanya dieksekusi satu kali. Itu tidak terjadi dengan CTE, atau dengan mengganti dua IN dengan dua EXIS.

Rob Farley
sumber
3

Kueri Anda mungkin harus ditulis ulang sebagai existsbukanin

Lihat tautan ini untuk lebih banyak contoh.

Kueri Anda kemudian akan melihat sesuatu di sepanjang baris

select *
from Customers C
where exists (select 'x' from ordertable o where c.orderid = o.orderid) 
or exists (select 'x' from ordertable o where c.secondaryOrderId = o.orderid) 

Jika kedua subkueri itu sama, Anda bisa menghapus salah satunya dan menggabungkannya seperti itu

select *
from Customers C
where exists (select 'x' from ordertable o where c.orderid = o.orderid or c.secondaryOrderId = o.orderid) 
Tom V - coba topanswers.xyz
sumber
2

Mengapa tidak menggunakan Common Table Expression alias withklausa? Ini dirancang untuk tujuan ini (antara lain).

with orderIds as (
  select orderId
  from ...
)
select *
from Customers
where orderId in (select orderId from orderIds) 
or secondaryOrderId in (select orderId from orderIds);

Lihat https://msdn.microsoft.com/en-us/library/ms175972%28v=sql.105%29.aspx untuk dokumentasi Microsoft.

Colin 't Hart
sumber
3
Tidak terlalu banyak manfaat dengan melakukan ini dalam hal waktu yang diambil. CTE tidak di-cache dan akan dieksekusi dua kali direferensikan. stackoverflow.com/questions/22041244/…
Mark Sinkinson
1
BAIK. Tampaknya setiap DBMS menangani CTE secara berbeda.
Colin 't Hart
CTE tidak dirancang untuk tujuan ini. Itu masih akan diperluas ke permintaan utama dua kali. Coba dan lihat ...
Rob Farley
1
Dan dokumentasi Microsoft menyesatkan "[A CTE] dapat dianggap sebagai set hasil sementara" yang saya artikan artinya hasil di-cache atau disimpan seperti tabel sementara. Sekarang ada solusi T-SQL lain yang belum disebutkan.
Colin 't Hart
@ Colin'tHart Selamat datang di dunia dokumentasi Microsoft :-)
Mark Sinkinson