Tek bir SELECT deyiminde birden çok aralık için dönüş sayıları


9

fooBaşka şeylerin yanı sıra, score0 - 10 arasında değişen bir sütun var bir Postgres veritabanı tablo var . Toplam sorgu sayısı, 0 ile 3 arasında puan sayısı, 4 arasında puan sayısı döndürmek için bir sorgu istiyorum ve 6 ve 7 ile 10 arasındaki puanların sayısı. Aşağıdaki gibi bir şey:

SELECT
  COUNT(*) as total,
  COUNT(
    SELECT * from foo where score between 0 and 3;
  ) as low,
  COUNT(
    SELECT * from foo where score between 4 and 6;
  ) as mid,
  COUNT(
    SELECT * from foo where score between 7 and 10;
  ) as high
FROM foo;

Bunu denedim, ama bir hata var SELECTiçinde COUNTtablolar. Bunu nasıl yapabileceğime dair bir fikrin var mı? Eminim Postgres'te çok basit bir yol var. Google için doğru şartları bulamıyorum.

Yanıtlar:


7

SUM()Her sayı aralığı için sütun başına koşullu ifadeler kullanın . Toplam, yalnızca SUM(1)tablodaki tüm verilerin aralıklardan birinde olduğunu varsayarak toplanabilir - eğer değilse, diğerleriyle olduğu gibi kısıtlayın.

select sum(case when score between 0 and 3 then 1 else 0 end) as minrange,
       sum(case when score between 4 and 6 then 1 else 0 end) as midrange,
       sum(case when score between 7 and 10 then 1 else 0 end) as maxrange,
       sum(1) as total
from foo;

SQL Fiddle bağlantısı .


8

FILTERPostgres 9.4 ve sonraki sürümlerinde toplu fıkra

Postgres 9.4'ten beri temiz ve hızlı (SQL standardı) bir yol var:

SELECT count(*) FILTER (WHERE score BETWEEN 0 AND 3)  AS low
     , count(*) FILTER (WHERE score BETWEEN 4 AND 7)  AS mid
     , count(*) FILTER (WHERE score BETWEEN 8 AND 10) AS high
     , count(*)                                       AS total
FROM   foo;

totalekler low, midve highNULL veya diğer değerler söz konusu olmadıkça,.

Bağlantılar:

Ayrıca aşağıda okuyun.

Postgres 9.3-

Birkaç teknik var:

@Phil , standart yolu bir CASEaçıklama ile sağladı (bunun dışında sum(1), standart yol değildir). Daha kısa bir form kullanmayı seviyorum:

SELECT count(score BETWEEN 0 AND 3  OR NULL) AS low
     , count(score BETWEEN 4 AND 6  OR NULL) AS mid
     , count(score BETWEEN 7 AND 10 OR NULL) AS high
     , count(*)                              AS total
FROM   foo;

Değerleriniz sorunuzda tanımlandığı gibiyse (yalnızca 0- 10mümkün), daha da basitleştirin:

SELECT count(score < 4 OR NULL)             AS low
     , count(score BETWEEN 4 AND 6 OR NULL) AS mid
     , count(score > 6 OR NULL)             AS high
     , count(*)                             AS total
FROM   foo;

Biraz daha kısa, ancak daha hızlı.

Ustaca farklılıklar

Orada küçük farklar karşılaştırıldığında sum()içinde Phil cevap :

  • En önemlisi, belge başına :

    countHiçbir satır seçilmediğinde, bu işlevler dışında null değer döndürdüğüne dikkat edilmelidir . Özellikle, sumhiçbir satır null döndürmez, beklendiği gibi sıfır değil, ...

  • count(*) olduğu standart yol ve biraz daha hızlı sum(1). Yine null vs. 0 uygulanır.

Bu sorguların her ikisi de (Phil dahil) null değerlerini sayar total. Bu istenmiyorsa, bunun yerine şunu kullanın:

count(score) AS total_not_null

SQL Fiddle , sayfa 9.3.
db <> keman burada pg 10'da.

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.