PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

GROUP BY + CASE oświadczenie

Twoje zapytanie będzie już działać — z wyjątkiem tego, że napotykasz konflikty nazw lub po prostu mylisz kolumnę danych wyjściowych (CASE wyrażenie) z kolumną źródłową result , który ma inną treść.

...
GROUP BY model.name, attempt.type, attempt.result
...

Musisz GROUP BY Twój CASE wyrażenie zamiast kolumny źródłowej:

...
GROUP BY model.name, attempt.type
       , CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END
...

Lub podaj alias kolumny to jest inne niż jakakolwiek nazwa kolumny w FROM lista - w przeciwnym razie ta kolumna ma pierwszeństwo:

SELECT ...
     , CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END AS result1
...
GROUP BY model.name, attempt.type, result1
...

Pod tym względem standard SQL jest dość specyficzny. Cytując instrukcję tutaj:

Nazwa kolumny wyjściowej może być używana do odwoływania się do wartości kolumny w ORDER BY i GROUP BY klauzul, ale nie w WHERE lub HAVING klauzul;w zamian musisz napisać wyrażenie.

Oraz:

Jeśli ORDER BY wyrażenie to prosta nazwa, która pasuje zarówno do nazwy kolumny wyjściowej, jak i nazwy kolumny wejściowej, ORDER BY zinterpretuje to jako nazwę kolumny wyjściowej. Jest to przeciwieństwo wyboru GROUP BY sprawi, że w tej samej sytuacji. Ta niespójność ma być kompatybilna ze standardem SQL.

Pogrubienie podkreślenie moje.

Tych konfliktów można uniknąć, używając odniesień pozycyjnych (liczby porządkowe) w GROUP BY i ORDER BY , odwołując się do elementów w SELECT lista od lewej do prawej. Zobacz rozwiązanie poniżej.
Wadą jest to, że może to być trudniejsze do odczytania i podatne na edycje w SELECT listę (można zapomnieć o odpowiednim dostosowaniu referencji pozycyjnych).

Ale nie trzeba dodać kolumnę day do GROUP BY klauzula, o ile zawiera stałą wartość (CURRENT_DATE-1 ).

Przepisany i uproszczony z odpowiednią składnią JOIN i referencjami pozycyjnymi może wyglądać tak:

SELECT m.name
     , a.type
     , CASE WHEN a.result = 0 THEN 0 ELSE 1 END AS result
     , CURRENT_DATE - 1 AS day
     , count(*) AS ct
FROM   attempt    a
JOIN   prod_hw_id p USING (hard_id)
JOIN   model      m USING (model_id)
WHERE  ts >= '2013-11-06 00:00:00'  
AND    ts <  '2013-11-07 00:00:00'
GROUP  BY 1,2,3
ORDER  BY 1,2,3;

Zauważ też, że unikam nazwy kolumny time . To zastrzeżone słowo i nigdy nie powinno być używane jako identyfikator. Poza tym twój „czas” to oczywiście timestamp lub date , więc jest to raczej mylące.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak przekonwertować ciąg na wartość liczbową w PostgreSQL

  2. Dlaczego postgres nie używa indeksu w moim zapytaniu

  3. Oracle odpowiednik Postgresa DISTINCT ON?

  4. Dynamiczna funkcja zapytań Postgres

  5. Zmień typ kolumny i ustaw wartość niepustą