SQL въпрос (към колеги програмисти)

November 19, 2007

Може ли да ми кажете, защо тази заявка връща 1, а не грешка? Пуля се тук защо една ултраважна заявка не ми работи, а аз съм изтървал напрактика ВСИЧКО В НЕЯ =)

mysql> select count(*) as c;
+---+
| c |
+---+
| 1 |
+---+
1 row in set (0.67 sec)

Пействам го от MySQL, но в SQL Server е същото, та предполагам това е обичайният начин, по който трябва да работи.

Ето допълнение:

mysql> select *;
ERROR 1096 (HY000): No tables used

MS SQL:
select *
Server: Msg 263, Level 16, State 1, Line 1
Must specify table to select from.

Публикувано в: Гърнето с боба 16 коментара RSS 2.0

Ако постът ви харесва, цъкнете на сърцето:

Коментари

16 коментара на “SQL въпрос (към колеги програмисти)”

  1. Даниел Панев on November 19th, 2007 14:58

    Ми като го пуснеш в някоя база данни (примерно 9i, 10g, 11g ;) ) не работи и си дава нормалното и очаквано съобщение за грешка.
    А какво ти показва explain plan или както там се казва в mysql и ms sql server?

  2. SuperCow on November 19th, 2007 15:06

    Нещо не виждам FROM клаузата.

    SELECT count(*)
    FROM table_name

  3. moni on November 19th, 2007 15:19

    select count(5); също връща 1, така че вероятно е нормално агрегатна функция да върне такъв резултат.
    от друга страна select count(null) връща 0

    явно всичко опира до това, как звездичката се интерпретира от count

  4. Свилен on November 19th, 2007 15:36

    Объркването идва от “интуитивното” определение, че “*” в COUNT означава нещо като “кое-да-е”, “всички” (ала “rm -rf *”)

    Изглежда, че COUNT(*) е “по-специален” – взето от manual-a:

    “COUNT(*) is somewhat different in that it returns a count of the number of rows retrieved, whether or not they contain NULL values.”

    SQL позволява изрази от вида “SELECT 1+1″, които винаги връщат 1 ред, следователно SELECT COUNT(1+1) отново е 1 (“един върнат ред като резултат”). Само, че SELECT COUNT(NULL) е 0 защото:

    “COUNT(expr) returns a count of the number of non-NULL values of expr in the rows retrieved by a SELECT statement”.

    Ето един по дълъг пример:

    mysql> select COUNT(t) FROM (SELECT NULL as t) as t2;
    +----------+
    | COUNT(t) |
    +----------+
    | 0 |
    +----------+
    1 row in set (0.00 sec)

    mysql> select COUNT(*) FROM (SELECT NULL as t) as t2;
    +----------+
    | COUNT(*) |
    +----------+
    | 1 |
    +----------+
    1 row in set (0.00 sec)

    Не е ли забавен SQL?

  5. dzver on November 19th, 2007 15:59

    Даниел, има Execution plan, който връща следната последователност (към всяко има подробности, които не ни касаят особено).

    Constant scan: 92%
    Stream aggregate: 8%
    Compute scalar: 0%
    SELECT: 0%

    Constant Scan Showplan Operator

    The Constant Scan operator introduces one or more constant rows into a query. A Compute Scalar operator is often used after a Constant Scan to add columns to a row produced by the Constant Scan operator.

    т.е. не знаем защо го прави, но знаем как го прави :)

  6. dzver on November 19th, 2007 16:06

    @Свилен: това само прави нещата по-странни :)
    @SuperCow: правилно си забелязала, за това става въпрос в поста.
    @Даниел explain в mysql прави друго, не връща полезна информация в случая.

  7. Даниел Панев on November 19th, 2007 16:15

    Ми предполагам, че са решили да ти спестят писането на това from (select null as t) и за това…

  8. uv on November 19th, 2007 17:11

    типично в sql стил ми изглежда select count(*) без from да върне 1 ;)

  9. Георги on November 19th, 2007 18:12

    Ми …

    mysql> select count(*) as c;
    +—+
    | c |
    +—+
    | 0 |
    +—+
    1 row in set (0.02 sec)

    mysql> select version();
    +————-+
    | version() |
    +————-+
    | 5.0.24a-log |
    +————-+
    1 row in set (0.01 sec)

  10. Свилен on November 19th, 2007 18:27

    Ми (x2):

    mysql> select count(*) as c;
    +—+
    | c |
    +—+
    | 1 |
    +—+
    1 row in set (0.01 sec)

    mysql> select version();
    +————————-+
    | version() |
    +————————-+
    | 5.0.37-community-nt-log |
    +————————-+
    1 row in set (0.00 sec)

  11. Георги on November 19th, 2007 23:29

    @Свилен
    Ти уби всичко детско в мен… :)

  12. uv on November 20th, 2007 01:30

    и аз:

    mysql> select count(*) as c;
    +—+
    | c |
    +—+
    | 1 |
    +—+
    1 row in set (0.00 sec)

    mysql> select version();
    +—————–+
    | version() |
    +—————–+
    | 4.1.22-standard |
    +—————–+
    1 row in set (0.00 sec)

  13. uv on November 20th, 2007 01:41

    ако “COUNT(*) is somewhat different in that it returns a count of the number of rows retrieved, whether or not they contain NULL values.” то за да изведе въобще някакъв резултат, sql-а ще избълва един row. по тази логика излиза редно резултатът да е 1, а не 0. идея си нямам 5.0.24a-log как я докарва тая 0. но изглежда като оптимизация за скорост. във всеки случай не мога да измисля какъв трик се опитваш да извършиш с участието на точно тая заявка ;)

  14. t0sh on November 21st, 2007 13:07

    минете на орацле – по-добрата боза ;)

  15. хасенчик on November 22nd, 2007 10:34

    При мен:

    mysql> select count(*) as c;
    +—+
    | c |
    +—+
    | 0 |
    +—+
    1 row in set (0.00 sec)

    Странно би било да е 1 ;)

  16. хасенчик on November 22nd, 2007 10:38

    И разбира се …

    mysql> select version();
    +———–+
    | version() |
    +———–+
    | 5.0.18-nt |
    +———–+
    1 row in set (0.00 sec)

Оставете отговор