Tajuplné MySQL

English version of this post available here

MySQL někdy dokáže překvapit. Teď jsem například narazil na toto: Mám tento SQL dotaz:

SELECT id, username, locked, c.*,
(SELECT COUNT(*)
FROM web_login_users
WHERE user=id AND (NOW()-last_action)<600) AS login_count
FROM web_users
LEFT JOIN web_user_information AS c ON (id=user)

Ten bez problému funguje a jako jeden ze sloupců se vrátí sloupec login_count. Chtěl jsem vybrat pouze řádky, kde je login_count větší než jedna. Intuitivně jsem zkusil toto:

SELECT id, username, locked, c.*,
(SELECT COUNT(*)
FROM web_login_users
WHERE user=id AND (NOW()-last_action)<600) as login_count
FROM web_users
LEFT JOIN web_user_information AS c ON (id=user)
WHERE login_count > 1

To ale nefunguje. MySQL hlásí, že nezná sloupec login_count.

Zajímavé je, že toto funguje:

SELECT id, username, locked, c.*,
(SELECT COUNT(*) FROM web_login_users
WHERE user=id AND (NOW()-last_action)<600) AS login_count
FROM web_users
LEFT JOIN web_user_information AS c ON (id=user)
ORDER BY login_count
Bude se to muset zřejmě obejít přes JOIN.

Po několika pokusech a konzultaci s kamarádem se vzdávám.

Pokus s JOIN

SELECT id, username, locked, c.*,
COUNT(login_users.user) AS login_count
FROM web_users
LEFT JOIN web_user_information AS c ON (id=user)
LEFT OUTER JOIN web_login_users AS login_users
ON (user=id AND (NOW()-last_action)<600)
WHERE login_count > 0

končí stejnou hláškou jako předešlé (Unknown column ‚login_count‘ in ‚where clause‘).

Toto se mi sice nelíbí, ale alespoň to funguje:

SELECT id, username, locked, c.*,
(SELECT COUNT(*) FROM web_login_users WHERE
user=id AND (NOW()-last_action)<600) AS login_count
FROM web_users LEFT JOIN web_user_information AS c ON (id=user)
WHERE (SELECT COUNT(*) FROM web_login_users
WHERE user=id AND (NOW()-last_action)<600) > 0

Tags: ,

2 Responses to “Tajuplné MySQL”

  1. Milan napsal:

    Zkus výstup seskupit pomocí „group by“ a podmínky pro skupiny pak nejsou pomocí „where“, ale „having“.

  2. honza napsal:

    Děkuji za radu. To opravdu funguje tak, jak jsem si původně představoval.

    Teoreticky by přece GROUP BY ale nemělo být potřeba, když agregační funkce používám jenom ve vnořeném SELECTu a WHERE podmínkou omezuji pouze podle jednoho sloupce, ne?

Leave a Reply