Sıfır satır eşleşse bile SEÇİM'in sabit bir değer döndürmesi


15

Bu select deyimini düşünün:

SELECT *, 
       1 AS query_id 
FROM players 
WHERE username='foobar';

Bir oyuncunun diğer sütunlarıyla query_idbirlikte değer 1içeren sütunu döndürür .

İnsan nasıl Yukarıdaki SQL en azından geri dönüş yapar query_idve 1hatta seçkin buluntular ise hiçbir satır eşleşen?

BTW, bu PostgreSQL 8.4.

Yanıtlar:


22
SELECT col1, 
       col2, 
       col3, 
       1 AS query_id 
FROM players 
WHERE username='foobar'
union all 
select null,
       null,
       null,
       1
where not exists (select 1 from players where username = 'foobar');

Alternatif olarak ( ikinci bir alt seçime gerek olmadığından daha hızlı olabilir ):

with qid (query_id) as (
   values (1)
) 
select p.*, 
       qid.query_id
from qid 
  left join players as p on (p.useranme = 'foobar');

Yukarıdakileri daha "kompakt" bir temsile yeniden yazabilirsiniz:

select p.*, 
       qid.query_id
from (values (1)) as qid (query_id)
  left join players as p on (p.useranme = 'foobar');

Ama açık CTE ( with...) daha okunaklı olduğunu düşünüyorum (her zaman izleyicinin gözünde olmasına rağmen).


1
İlk örneği denerken, ALL anahtar sözcüğü gerekli değil mi?
Nathanael Weiss

2
@NatWeiss: Belirli bir düzen gerekiyorsa, sahip bir tedarik order by. İkincisi, tam olarak bir satır ve bir sütun içeren bir sanal tablo "oluşturur" ve bir dış birleştirme yapar (herhangi bir "gerçek" birleştirme koşulu olmadan), böylece her zaman en az bir satırı geri alırsınız. select *Üretim kodunda kullanmak kötü bir stildir. Yapma. Her zaman ihtiyacınız olan sütunları listeleyin. select *gerektiğini sadece ad-hoc sorguları kullanılabilir.
a_horse_with_no_name

2
@NatWeiss: "diğer birleştirmeler" için hangi "alternatif sözdiziminden" bahsediyorsunuz. Ve neden left joinokunamaz olduğunu düşünüyorsun ?
a_horse_with_no_name

2
@NatWeiss: yan tümcesinde örtük birleştirme kötü kodlama stili ve kaçınılmalıdır. Size bir hata vermeden istenmeyen cartesianların birleşmesine yol açabilir. Ve birleştirme ve filtrelemenin iki (ilişkisel) kavramını açıkça ayırır
a_horse_with_no_name

4
re: "birleşim" deyiminin "tüm" değiştiricisi gerekli değildir: UNION ALLbazen UNIONsorgu planlayıcısına UNIONed sorgularından çıkan yinelenen satırların olmasını beklemediğinizi veya bunların çıkmasını istersiniz. ALLDeğiştirici olmadan, DISTINCTanahtar kelimede olduğu gibi yinelenen satırların kaldırılmasını (her biri yalnızca bir tanesini) istediğinizi varsayar ve sonuçların ek bir süre başvurması + yeniden taraması gerekebileceğini garanti eder. Bu nedenle ALL, UNIONözellikle çıkış satırı çoğaltması gerekmediği sürece ile kullanın .
David Spillett

7

Yalnızca bir veya sıfır satır geri bekliyorsanız, bu da işe yarar:

SELECT
  max(col1) col1,
  max(col2) col2, 
  1 AS query_id 
FROM
  players 
WHERE
  username='foobar';

Bu, bir satır bulunmazsa sorgu_kimliği dışında tüm değerlerin null değerine sahip olduğu bir satır döndürür.


2
İyi numara. Tek dezavantajı, username = 'foobar'
koşulla

1
Coalesce () de bu şekilde kullanılabilir mi?
Nathanael Weiss

1
Coalesce, tablodan hiçbirinin yansıtılmadığı bir satır oluşturmaz.
David Aldridge

1
@a_horse_with_no_name evet, ancak tablo ve sütun adları yüklemin tablo için bir aday anahtarında olduğunu düşünse de sıfır veya bir satır yansıtılacaktır.
David Aldridge

3

Burada geç saatlerde chiming, ama burada çalışan bir sözdizimi (en azından 9.2, önceki sürümleri denemedim).

SELECT (COALESCE(a.*,b.*::players)).*
FROM ( SELECT col1,  col2,  col3, 1 AS query_id 
       FROM players WHERE username='foobar' ) a
RIGHT JOIN (select null col1, null col2, null col3, 1 col4) b
ON a.query_id = b.col4;

"Boş" satırını yalnızca "a" nın tüm içeriği boşsa döndürür.

Zevk almak. / bithead


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.