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?

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.


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) 

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.


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.