HAVING místo WHERE rubrika: Databáze: SQL

8 rmaslo
položil/-a 1.2.2018
 
upravil/-a 1.2.2018

Mějme třeba zjistit položky všech faktur které jsou větší než nějaká částka. Samozřejmě s tím že tu částku je potřeba vypsat. První co člověka napadne je něco jako:
a)

SELECT id, cena*pocet*(1+dan/100) AS sumcena FROM faktury_rozpis WHERE cena*pocet*(1+dan/100) > 100000

na dotazu mě nepřijde hezké 2x zapsaný vzorec výpočtu, který se také zřejmě 2x počítá. Výsledek "sumcena" není možno použít ve WHERE protože se napřed určuje podmínka WHERE a až pak se osazují hodnoty sloupců. Nicméně lze napsat:
b)

SELECT id, cena*pocet*(1+dan/100) AS sumcena FROM faktury_rozpis HAVING sumcena > 100000

Protože HAVING se aplikuje až po osazení sloupců.

Který způsob by jste zvolili (výkon, přehlednost či jiné zkušenosti)?

------------------------------------------ Doplnění 2018-02-01
Mám dojem, že zatím vítězí:
c)

SELECT * FROM (SELECT id, cena*pocet*(1+dan/100) AS sumcena FROM faktury_rozpis) AS T1 WHERE sumcena > 100000

Komentáře

  • harrison314 : Nenapisal si aka to je databaza. 1.2.2018
  • rmaslo : Databaze MySQL 1.2.2018
odkaz Vyřešeno
4 vojtech.kurka
odpověděl/-a 2.2.2018

Pokud ti jde opravdu o výkon, tak nikdy nechceš použít WHERE na výrazu místo sloupce. Když používáš výraz, MySQL nemůže pro vyhodnocení WHERE podmínky použít index.

Proto bych na tu tabulku přidal VIRTUAL COLUMN, ve kterém bude výsledek výrazu (cenapocet(1+dan/100)) a na něj samozřejmě vhodný index.

ALTER TABLE faktury_rozpis ADD total_with_tax DECIMAL(11,2) GENERATED ALWAYS AS (cena*pocet*(1+dan/100)) VIRTUAL NOT NULL;
ALTER TABLE faktury_rozpis ADD INDEX total_with_tax(total_with_tax);

Finalni dotaz pak bude

SELECT id, total_with_tax AS sumcena 
  FROM faktury_rozpis
WHERE total_with_tax > 100000;

Komentáře

  • Marekzprahy : V PL/SQL světě je to asi běžné, ale v MySQL bych se přimlouval za to nedávat logiku do databáze, navíc takto schovanou. Je to podle mě zbytečná magie. K původní otázce: Jde-li o výkon, nechal bych výpočet total_with_tax na aplikaci a ukládal ho současně s ostatními hodnotami. Jinak bych volil variantu A, tedy s where. Varianta C je IMHO hodně podobná variantě B, používám ji v případě, kdy nechci z nějakého důvodu sahat na původní sql dotaz (třeba mám jeden dotaz na výpis všech elementů a univerzální komponenta tabulky si k němu takhle přidá filtrování a řazení). 9.2.2018

Pro zobrazení všech 5 odpovědí se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.