Bir alt sorgunun tam olarak bir farklı sonucu ve belirli bir değeri kısaca olup olmadığını nasıl kontrol edebilirim?


10

Kendimi aşağıdakileri yazarken buldum:

select 'yes' 
where exists(select * from foo where val=1)
and not exists(select * from foo where val<>1);

ve çok fazla okunabilirlikten ödün vermeden daha özlü bir yol olup olmadığını merak etmek.

Yanıt olarak gönderdiğim bir yol buldum ama bundan tamamen memnun değilim ve alternatiflerle çok ilgileneceğim

Bu durumda valiçinde benzersizdir foo- kopya yok


Alt sorgu sonucunda tam olarak bir satır istediğinizi doğru anladım mı?
Erwin Brandstetter

Hangi alt sorgu?
Jack diyor ki topanswers.xyz

Başlıkta bahsettiğiniz kişi. Bunun "farklı" dan önce veya sonra bir sonuç olup olmayacağından emin değildim.
Erwin Brandstetter

Ah evet, bir :) Doğrusu karışıklığa benim alt sorguda kastettiğini cevap - sizin de kullanabilirsiniz örneğin çok daha spesifik ve esnek olan count(distinct val)benim gerçek dünya durumda hiç fark etmez olsa da,
Jack deneyin diyor topanswers.xyz

Yanıtlar:


8

Özlü, hızlı (özellikle birçok satırda), okunabilirlikle ilgili favorim ve dupes ile de çalışacaktı:

SELECT count(*) = 1 AND min(val) = 1 FROM foo;

İade TRUE/ FALSE.. veya NULL- Yalnızca ile tam olarak bir satırda durumunda val IS NULL, çünkü count()hiçbir zaman geri döner NULLveya hiç üst üste.

1Örnekteki ikinci örnek, ilk örnekle aynıdır, örneğin.


Sorudaki sorgu NULLdeğerlerle başarısız oluyor . Basit demosu düşünün:

CREATE TABLE foo (id int, val int);
INSERT INTO foo VALUES (1, 1),(2, NULL);

SELECT 'yes' 
WHERE      EXISTS(SELECT * FROM foo WHERE val =  1)
AND    NOT EXISTS(SELECT * FROM foo WHERE val <> 1);

IS DISTINCT FROMbunu düzeltir, ancak yine de val, bu dava için dışladığınız kopyalarla başarısız olabilir .


Cevabınız iyi çalışıyor. Satır
döndürür 'yes'/ satır yok.

Yine de bu daha kısa formu tercih ederim. PostgreSQL'in (Oracle'ın aksine) uygun bir booleantüre sahip olduğunu unutmayın .

SELECT array_agg(val) = array[1] FROM foo;

TRUE/ FALSE/ Değerini döndürür NULL.


mükemmel, teşekkürler, daha iyi bir yol olacağını biliyordum :)
Jack denemek topanswers.xyz diyor

5

@ Erwin'in cevabında bir varyasyon. Hayır COUNT(), sadece MIN()ve MAX(). Büyük tablo ile biraz daha verimli olabilir ve (sizin durumunuzda değil) kopya val:

SELECT MIN(val) = 1 AND MAX(val) = 1 FROM foo;

+1 teşekkürler. Elbette
null'ları

@Jack: Evet. Masanızda null değeri var mı? Yoksa her iki durum için (ister olsun ister olmasın) cevap mı istiyorsunuz?
ypercubeᵀᴹ

benim yok - ben de kullanabilirsiniz :)
Jack denemek topanswers.xyz diyor ki

Eşleşen bir dizine sahip daha büyük tablolarda çok daha hızlı olurdu , ancak sorgu sonuçlarını test ederken olduğu gibi böyle bir dizinin yokluğunda aynı performansı gösterir.
Erwin Brandstetter


1

Bu, bir döner true, falseveya boş bir sonucu:

 select j.val is null 
 from foo left join foo as j on j.val <> foo.val 
 where foo.val = 1 limit 1;

ilk bakışta, nerede falsedeğerler varsa bu geri gelmiyor gibi görünüyor ? fooval<>1
Jack diyor ki topanswers.xyz

@JackDouglas Oh, üzgünüm. Görevi ilk kez yanlış anladım. Sabit.
grayhemp

İşler - NULLbu durumda göz ardı edilmemiş değer olarak hariç .
Erwin Brandstetter

@ErwinBrandstetter bence NULLkullanarak çalışılabilir IS [NOT] DISTINCT FROM.
grayhemp

1
@grayhemp: Bu durumda değil. LEFT JOIN foo j ON j.val <> foo.valile j.val IS NULLbaşlayan bir satırı algılayamaz . Eğer eklerseniz , iki vakayı birbirinden ayırmak için tanımlı ON j.val IS DISTINCT FROM foo.valbaşka bir sütunu kontrol etmeniz gerekir . Ancak ek sütun tanımlanmamıştır. jNOT NULL
Erwin Brandstetter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.