Mysql
 sql >> база данни >  >> RDS >> Mysql

Как правилно да GROUP BY в MySQL?

Първото нещо, което трябва да стане ясно, е, че SQL не е MySQL.

В стандартния SQL не е разрешено групирането по подмножество от неагрегирани полета. Причината е много проста. Да предположим, че изпълнявам тази заявка:

SELECT color, owner_name, COUNT(*) FROM cars
GROUP BY color

Това запитване няма да има никакъв смисъл. Дори да се опитам да го обясня би било невъзможно. Със сигурност избира цветове и брои количеството коли за цвят. Въпреки това, той също така добавя owner_name поле и може да има много собственици за даден цвят, какъвто е случаят с White цвят. Така че, ако може да има много owner_name стойности за един color което се оказва единственото поле в GROUP BY клауза... след това кое owner_name ще бъде върнато?

Ако е необходимо да се върне owner_name тогава трябва да се добави някакъв вид критерии, за да се избере само един от тях, например първият по азбучен ред, който в този случай би бил John . Тези критерии биха довели до добавяне на агрегатна функция MIN(owner_name) и след това заявката отново ще има смисъл, тъй като ще се групира поне по всички неагрегирани полета в оператора select.

Както можете да видите, има ясна и практична причина стандартният SQL да бъде негъвкав в групирането. Ако не беше, бихте могли да се сблъскате с неудобни ситуации, в които стойността за колона ще бъде непредсказуема и това не е хубава дума, особено ако изпълняваната заявка ви показва транзакциите по банковата ви сметка.

След като казахме това, тогава защо MySQL позволява заявки, които може да нямат смисъл? И още по-лошо, грешката в заявката по-горе може да бъде просто синтактично открита! Краткият отговор е:производителност. Дългият отговор е, че има определени ситуации, в които въз основа на отношенията с данни получаването на непредвидима стойност от групата ще доведе до предвидима стойност.

Ако все още не сте го разбрали, единственият начин, по който можете да предвидите стойността, която ще получите от вземането на непредвидим елемент от група, ще бъде ако всички елементи в групата са еднакви. Ясен пример за тази ситуация е в примерната заявка в същия въпрос. Вижте как owner_id и owner_name се отнася в таблицата. Ясно е, че даден owner_id , напр. 2 , можете да имате само един отделен owner_name . Дори да имате много редове, като изберете някой, ще получите Mike като резултат. На официалния жаргон на базата данни това може да се обясни като owner_id функционално определя owner_name .

Нека разгледаме по-отблизо тази напълно работеща MySQL заявка:

SELECT owner_id, owner_name, COUNT(*) total FROM cars
GROUP BY owner_id

Даден всеки owner_id това ще върне същото owner_name , така че го добавяте към GROUP BY клаузата няма да доведе до повече върнати редове. Дори добавяне на агрегирана функция MAX(owner_name) няма да доведе до по-малко върнати редове. Получените данни ще бъдат абсолютно същите. И в двата случая заявката ще бъде незабавно превърната в правна стандартна SQL заявка, тъй като поне всички неагрегирани полета ще бъдат групирани по. Така че има 3 подхода за получаване на едни и същи резултати.

Въпреки това, както споменах по-рано, това нестандартно групиране има предимство в производителността. Можете да проверите тази толкова подценена връзка в който това е обяснено за повече подробности, но ще цитирам най-важната част:

Едно нещо, което си струва да се спомене е, че резултатите не са непременно грешни но по-скоро неопределено . С други думи, получаването на очакваните резултати не означава, че сте написали правилната заявка. Написването на правилната заявка винаги ще ви даде очакваните резултати.

Както можете да видите, може да си струва да приложите това разширение на MySQL към GROUP BY клауза. Както и да е, ако това все още не е 100% ясно, тогава има практическо правило, което ще гарантира, че вашето групиране винаги ще бъде правилно:Винаги групирайте поне по всички неагрегирани полета в клаузата за избор . Може да губите няколко цикъла на процесора в определени ситуации, но това е по-добре, отколкото да връщате неопределено резултати. Ако все още се страхувате да не групирате правилно, тогава променете ONLY_FULL_GROUP_BY SQL режимът може да е последна мярка :)

Нека вашето групиране е правилно и ефективно... или поне правилно.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Концепции за Angular 2 и MySQL

  2. Сортиране на полето varchar числово в MySQL

  3. Защо да използвам DB::raw вътре в DB::select в Laravel?

  4. MySQL заявка:Съпоставете стойност, разделена със запетая, с колона, съдържаща низ, разделен със запетая

  5. Как да конфигурирате MySQL да бъде чувствителен към малки и големи букви