Най-добри практики за множество SQL извиквания за избягване на повтарящи се резултати

Трябва ли да се използват множество SQL извиквания, когато това може да се направи в едно извикване, ако едното извикване връща повтарящи се данни?

Например, и това е наистина прекалено опростена версия на това, което се опитвам да направя, ние искаме да получим информация за потребителите и техните любими групи. Ако го направих с едно обаждане, можех да направя:

SELECT userName, userAge, userGender, bandName FROM users NATURAL JOIN userBands NATURAL JOIN bands WHERE userID = 47

Това ще ми върне списък с всички групи, които потребителят харесва, но за всяка една ще върне потребителското име, възраст и пол.

Мога да направя две обаждания...

SELECT userName, userAge, userGender FROM users WHERE userID = 47
SELECT bandName FROM userBands NATURAL JOIN bands WHERE userID = 47

където първият просто връща основната информация веднъж, а вторият просто връща списъка с ленти. Има ли някаква най-добра практика с това? Има ли друг начин да подходя към това, който не осъзнавам? И какво, ако (както ще бъде в моя случай от реалния свят), че не са само две извиквания за разделяне на данните, а 4 или 5? Така че има много повече обаждания, но също така се връщат много повече външни данни, за да се направи това в едно обаждане.

Използвам PHP PDO, ако това има значение в отговора.


person Dan Goodspeed    schedule 14.12.2014    source източник
comment
Има режийни разходи за повикване, обикновено искате да ги сведете до минимум. Така че обикновено трябва да комбинирате свързани повиквания, когато има смисъл да го направите.   -  person Barmar    schedule 14.12.2014
comment
Изглежда пропускате ГРУПИРАНЕ ПО в първата заявка...   -  person Phantômaxx    schedule 14.12.2014
comment
Трябва да избягвате NATURAL JOIN, защото ще завърши със сравняване на две колони, които наистина не очаквате. Това е особено разпространено в големите производствени dbs, които имат склонност да имат колони за проверка (като inserted_at времеви клейма), които не са сравними в много ситуации (особено ако колоните не са с префикс имена на таблици - това се счита за шум в повечето случаи). Защо съхранявате възрастта, тъй като тя е производна стойност?   -  person Clockwork-Muse    schedule 14.12.2014
comment
Какво ще направите с резултатите?   -  person CL.    schedule 14.12.2014
comment
SQL заявката, която предоставих по-горе, е просто опростени/измислени имена на колони и други подобни, защото не исках да разсейвам хората с по-сложните обаждания, които правя. Въпреки че правя NATURAL JOIN, тъй като изградих базата данни с колони, специално именувани за целите на използването на NATURAL JOIN.   -  person Dan Goodspeed    schedule 15.12.2014


Отговори (2)


Има друг отговор, който е да комбинирате лентите в една колона с помощта на group_concat():

SELECT u.userName, u.userAge, u.userGender, group_concat(b.bandName)
FROM users u NATURAL JOIN
     userBands ub NATURAL JOIN
     bands b
WHERE userID = 47
GROUP BY u.userName, u.userAge, u.userGender;

Това ви дава по един ред на потребител със списъка с ленти.

Между другото, бих ви разубедил да използвате NATURAL JOIN. След това заявката зависи от метаданните за ключовете за присъединяване -- и малка промяна в структурите на таблицата може да окаже голямо влияние върху много заявки. Използвайте или изрична клауза on, или клауза using.

person Gordon Linoff    schedule 14.12.2014
comment
Супер, ще опитам това по-късно тази вечер. И използвам NATURAL JOIN, защото изградих базата данни с колони, специално именувани за целите на използването на NATURAL JOIN. :-) - person Dan Goodspeed; 15.12.2014
comment
Хм, току що го пробвах. group_concat() е малко хак, но мисля, че е най-доброто решение, представено за въпроса, който зададох. Благодаря. - person Dan Goodspeed; 15.12.2014

Това има смисъл, когато изпращате данни през мрежа до отдалечен потребител. Защо да губите честотна лента, изпращайки едни и същи данни отново и отново? За тази цел добър метод е да поставите данните в някаква XML структура.

<users>
  <user>
    <userdata1>...</userdata1>
    <...>...</...>
    <bands>
      <band>...</band>
      <band>...</band>
      ...
    </bands>
  </user>
</users>

Не се изпращат дублирани данни. Дали ще формирате тази структура от единичен набор от резултати с дублирани данни или от двата набора от резултати зависи от вас и вашия екип. Поиграйте си и с двете и решете кое е най-добро за вашата конкретна ситуация.

person TommCatt    schedule 14.12.2014
comment
Има ли начин SQLite да върне данните в XML? - person Dan Goodspeed; 15.12.2014
comment
stackoverflow .com/questions/17908023/ - person TommCatt; 15.12.2014
comment
Така че… предполагам, че това е не. - person Dan Goodspeed; 15.12.2014