Soru NEREDE col1, col2 IN (…) [Bileşik birincil anahtar kullanarak SQL alt kümesi]


Tablo verildiğinde foo birleşik birincil anahtarla (a,b)gibi bir sorgu yazmak için yasal bir sözdizimi var mı:

SELECT ... FROM foo WHERE a,b IN (SELECT ...many tuples of a/b values...);
UPDATE foo SET ... WHERE a,b IN (SELECT ...many tuples of a/b values...);

Bu mümkün değilse ve şemayı değiştiremezseniz, yukarıdaki denkliği nasıl yerine getirebilirsiniz?

Ayrıca, bu takma adlara yönelik arama isabetleri için "bileşik birincil anahtar", "alt seçim", "alt seçim" ve "alt sorgu" terimlerini burada da kullanacağım.

Düzenle: Standart SQL'in yanı sıra PostgreSQL ve SQLite 3 ile çalışacak olanların cevaplarıyla ilgileniyorum.


32
2018-01-07 04:14


Menşei




Cevaplar:


sqlite> create table foo (a,b,c);
sqlite> create table bar (x,y);
sqlite> select * from foo where exists (select 1 from bar where foo.a = bar.x and foo.b = bar.y);

Değiştirin select 1 from bar seninki ile select ... many tuples of a/b values ....

Veya geçici bir tablo oluşturun. select ... many tuples of a/b values ... ve yerine kullan bar..


24
2018-01-07 04:31





Sözdiziminiz Standart SQL'e çok yakın!

Aşağıdaki geçerli FULL SQL-92'dir ( Mimer SQL-92 Validator)

SELECT * 
  FROM foo 
  WHERE (a, b) IN (
                   SELECT a, b 
                      FROM bar
                  );

Tabii ki, her SQL ürünü tam SQL-92'i desteklemiyor (utanç!) Eğer Microsoft SQL Server'da desteklenen bu sözdizimini görmek isteyen herkes bunun için oy kullanabilir İşte.

Daha yaygın olarak desteklenen başka bir SQL-92 yapısı (ör. Microsoft SQL Server ve Oracle) INTERSECT Örneğin.

SELECT a, b
  FROM Foo
INTERSECT
SELECT a, b
  FROM Bar;

Bu yapıların düzgün bir şekilde ele alındığını unutmayın. NULL diğer önerilerden farklı olarak, burada örn. kullananlar EXISTS (<equality predicates>), birleştirilmiş değerler vb.


14
2018-01-07 11:27



Bu PostgreSql'de desteklenir. SELECT * FROM foo WHERE (a,b) IN ((1,2),(3,4)) - Taha Jahangir


Çok küçük bir hata yaptın. B'yi parantez içine almanız gerekir.

SELECT ... FROM foo WHERE (a,b) IN (SELECT f,d FROM ...);

Bu işe yarıyor!


6
2017-08-01 13:04





Önerdiğiniz IN sözdizimi geçerli bir SQL değil. EXISTS kullanan bir çözüm, tüm makul olarak uyumlu SQL RDBMS'lerinde çalışmalıdır:

 UPDATE foo SET x = y WHERE EXISTS
    (SELECT * FROM bar WHERE bar.c1 = foo.c1 AND bar.c2 = foo.c2)

Bunun özellikle performans açısından önemli olmadığını unutmayın.


4
2018-01-07 04:52



IN ve EXISTS aynı planla sonuçlanmalıdır çünkü bunlar semantik olarak aynıdır. En azından SQL Server'da yine aynı planı alırsınız. - gbn


    SELECT ...
      FROM foo
INNER JOIN (SELECT ...many tuples of a/b values...) AS results
        ON results.a = foo.a
       AND results.b = foo.b

Aradığın şey bu mu?


3
2018-01-07 04:20



Bu iyi görünüyor, çünkü durumda işe yaramaz UPDATE SQLite3'te UPDATE içinde katılımları desteklemiyor sorguları. Temel çok anahtarlı IN'nin yasal olup olmadığını (kısmen SQLite'de olmadığını okudum), ama aynı zamanda yardımcı olmak için çalışıyorum. bu soruyu cevapla. - Phrogz
Ah, güncelleme için emin değilim. Kafamı buna karşı vurmaya devam edeceğim ... - Stefan H
Bu benim için çalıştı. Çok teşekkürler!! - Rodrigo Almeida


Birleştirme ile, bu PostgreSQL ile çalışır:

SELECT a,b FROM foo WHERE a||b IN (SELECT a||b FROM bar WHERE condition);

UPDATE foo SET x=y WHERE a||b IN (SELECT a||b FROM bar WHERE condition);

2
2018-01-07 10:24



Bu a ve b değerlerine bağlı olarak kötü bir fikirdir. Birleşiminiz her zaman benzersiz olmayacaktır. = 22 ve b = 1 ile bir kayda sahip olabilirsiniz, başka bir kayda ise = 2 ve b = 21. Birbiriniz için birleşme 221 olacaktı! Bu sorunu önlemek için biraz daha iyi bir birleşme || '-' || b olacaktır. Başka bir sorun, birleştirme ile veritabanı yavaşça dizinleri kullanamaz çünkü sorgu yavaş olacaktır. - Otherside


Bir tabloda zaten mevcut olan değerlerin tuplesini gerektirmeyen bir çözüme ihtiyaç duyarsanız, listenizdeki ilgili tablo değerlerini ve öğeleri birleştirebilir ve ardından 'IN' komutunu kullanabilirsiniz.

Postgreslerde bu şöyle görünürdü:

SELECT * FROM foo WHERE a || '_' || b in ('Hi_there', 'Me_here', 'Test_test');

SQL'de iken bunun gibi bir şey görebileceğini düşünürdüm:

SELECT * FROM foo WHERE CONCAT(a, "_", b) in ('Hi_there', 'Me_here', 'Test_test');


0
2017-11-09 05:29





JOINS ve INTERSECTS yerine geçmek INama bunun yerine geçecek kadar açık değiller. NOT INör. TableA içine TableB zaten var olmadıkları yer TableB nerede PK her iki tabloda da bir kompozit.

Şu anda SQL Server'da yukarıdaki birleştirme yöntemini kullanıyorum, ancak bu çok zarif bir çözüm değil.


0
2018-04-05 12:45



Şuna bak MERGE..USING..WHEN NOT MATCHED THEN INSERT... - onedaywhen