2013-04-02 2 views
2

Рассмотрим следующий простой пример:SQLite "COUNT (*)" Считается вредным?

prompt% sqlite3 test.db 
sqlite> create table employee (
      employee_id integer  primary key, 
      first_name varchar2(32) not null, 
      last_name  varchar2(32) not null 
     ); 

sqlite> insert into employee (first_name, last_name) values ('Bill', 'Smith'); 
sqlite> insert into employee (first_name, last_name) values ('Sally', 'Jones'); 
sqlite> insert into employee (first_name, last_name) values ('Bill', 'Jones'); 

sqlite> select first_name, count(*) from employee; 

Что будет результат?

наивный может предположить, что это будет:

Bill|2 
Sally|1 

Но опытный заметит, что ВЫБРАТЬ запрос отсутствует «GROUP BY», п. Oracle, при предъявлении этого запроса, по сути, бросить ошибку:

SQL ERROR: ORA-00937: not a single-group group function 

SQLite, однако, не жалуется, но вместо этого дает:

Bill|3 

, который кажется поддельным мне. .. Отображение общего количества строк может иметь смысл, я полагаю, но просто выбор последнего «first_name» кажется довольно произвольным и потенциально опасным.

Является ли это ошибкой или функцией, которую я просто не понимаю? Есть ли причина, по которой SQLite не предлагает аналогичную систему безопасности?

+0

Не имеет смысла использовать агрегатную функцию без предложения GROUP BY, когда вы не выбираете все строки. Подумайте, что вы даже считаете? Вы хотите «выбрать first_name, count (*) из группы сотрудников по первому имени;« – NullUserException

+0

»Может иметь смысл использовать агрегат без« GROUP BY », если все записи считаются находящимися в одной группе (и все, что вы хотите, это количество записей или наибольшее значение или что-то еще). Здесь не имеет значения значение «first_name». Это похоже на ошибку или, по крайней мере, на крайне низкую реализацию SQL. – mwigdahl

+0

Это идентичная реализация MySQL @mwigdahl. – Ben

ответ

5

Это все documented:

If the SELECT statement is an aggregate query without a GROUP BY clause, then each aggregate expression in the result-set is evaluated once across the entire dataset. Each non-aggregate expression in the result-set is evaluated once for an arbitrarily selected row of the dataset. The same arbitrarily selected row is used for each non-aggregate expression...

The single row of result-set data created by evaluating the aggregate and non-aggregate expressions in the result-set forms the result of an aggregate query without a GROUP BY clause. An aggregate query without a GROUP BY clause always returns exactly one row of data, even if there are zero rows of input data.

Проще говоря, нет никакой сети безопасности. Не забудьте GROUP BY, если вам это нужно.

+1

С [SQLite 3.7.11] (http://www.sqlite.org/releaselog/3_7_11.html) можно выбрать строку для неагрегированных выражений с помощью 'MIN' или' MAX'. Это совершенно нестандартно, но полезно в определенных ситуациях. –

Смежные вопросы