Topic: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Sveiki, reikia pagalbos rašant SELECT užklausą. šiuo atveju reikia SELECT užklausos naudojant JOIN, nes reikiamose lentelėse įrašų skaičius siekia 60 000 - 70 000.

Sąlygos tokios.
Yra 3 lentelės: user - darbuotojai, lead - klientai, entity - sąryšių lentelė.  Jų turinys pateikiamas žemiau. Lentelės 'lead' ir 'user' susiriša per 'entity' lentelę.

Užklausa turi išvesti tuos klientus, kurie priklauso darbuotojui 'admin'. Priklauso darbuotojui 'admin' REIšKIA, kad klientų, priklausančių darbuotojui 'admin' ir darbuotojui 'vadybininkas', 'company' lauko reikšmės yra VIENODOS.
Na kad lengviau suvokti, užklausos rezultatas turėtų būti:

leadid    company
7             niekadejas





lentelė "user":

id    name
1     admin
2     vadybininkas
3     buhalterija


lentelė "lead":

leadid     company
1            siglus
2            andrada
3            veikejas
4            niekadejas
5            pagauk veja
6            kasnis
7            niekadejas
8            falck


lentelė "entity":

id    userid   leadid
1       1           5
2       1           3
3       1           2
4       1           7
5       1           1
6       2           4
7       1           6
8       1           8
9       2           8



Dėkui

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Laba diena,

O pats bandei tą užklausą rašyti? Iš pirmo žvilgsnio ji neatrodo tokia jau ir sudėtinga, turint omenyje, kad šiame forume jau yra nemažai pavyzdžių, kaip tai padaryti? Gal turi parodyti nenusisekusią užklausą?

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Vat vienas iš variantų:


SELECT `vtiger_leaddetails_admin`.`company`

FROM  `lead` AS `lead_main`


INNER JOIN `lead` AS `lead_admin` ON `lead_admin`.`leadid` = `lead_main`.`leadid`

INNER JOIN `entity` AS `entity_admin`  ON `entity_admin`.`leadid` = `lead_admin`.`leadid`

INNER JOIN `users` AS `users_admin` ON `users_admin`.`id` = `entity_admin`.`userid` AND `users_admin`.`name` = 'admin'




INNER JOIN `lead` AS `lead_vadybininkas` ON `lead_vadybininkas`.`leadid` = `lead_main`.`leadid`

INNER JOIN `entity` AS `entity_vadybininkas` ON `entity_vadybininkas`.`leadid` = `lead_main`.`leadid`

INNER JOIN `users` AS `users_vadybininkas` ON `users_vadybininkas`.`id` = `entity_vadybininkas`.`id` AND `users_vadybininkas`.`name` = 'vadybininkas'




WHERE `users_admin`.`name` = 'admin' AND `lead_admin`.`company` = `lead_vadybininkas`.`company`



Bet čia atrenka tik tuos klientus, kurie priklauso abiems vartotojams pagal id, o kaip palygint pagal kompanijos pavadinimą man nepavyksta, kažką darau ne taip.
Aš neatkasu, kaip, tarkim, naudojant join'tus šiuo atveju teisingai prisijungti informaciją apie tuos klientus kurie priklauso darbuotojui 'vadybininkas' ir kad vėliau per WHERE galima būtų palyginti kompanijų pavadinimus iš laikinų lentelių priklausančių skirtingams darbuotojams? O gal aš per sudėtingai bandau padaryt :)

4 (edited by minius 2008-10-08 11:00:54)

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Arba tarkim ši dalis:


SELECT `vtiger_leaddetails_admin`.`company`

FROM  `lead` AS `lead_main`


INNER JOIN `lead` AS `lead_admin` ON `lead_admin`.`leadid` = `lead_main`.`leadid`

INNER JOIN `entity` AS `entity_admin`  ON `entity_admin`.`leadid` = `lead_admin`.`leadid`

INNER JOIN `users` AS `users_admin` ON `users_admin`.`id` = `entity_admin`.`userid` AND `users_admin`.`name` = 'admin'


išvada visus klientus, kurie priklauso tik darbuotojui 'admin', nepalyginant kaip reikia pagal kompanijos pavadinimą.

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Kai forumuose ką nors postini, pabandyk pasinaudoti BBKodais "code" ir/arba "quote" (-; Bus aiškiau visiems.

Toliau:
a) užklausose JOIN'ini lead lentelę su pačia savimi, Tavo atveju manau to nereikia;
b) cituoju:

Užklausa turi išvesti tuos klientus, kurie priklauso darbuotojui 'admin'.
Priklauso darbuotojui 'admin' REIšKIA, kad klientų, priklausančių darbuotojui 'admin' ir darbuotojui 'vadybininkas', 'company' lauko reikšmės yra VIENODOS.

čia nematau logikos... nes company laukas yra ne darbuotojo, o kliento?
c) kodėl dar labiau nesunormalizavus lentelės lead iš stulpelį company iškelti į atskirą lentelę?

Gal tiktų tokia užklausos gamybos eiga pradiniam variantui, esamoje situacijoje:
1) išrenkam klientus, kurie priklauso vadybininkui;
2) išrenkam klientus, kurie priklauso adminui;
3) sujungiam abu rezultatus ir paliekam tik tuos, kuriu kompanijos sutampa;

Jeigu nepavyks parašyti - pranešk (-;

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

a)  dar nesugalvojau kaip palyginti kompanijos laukus, nejungiant papildomai lead lentelės;
b) kokio užklausos man reikia manau geriausia atspindi pirmos mano žinutės vieta, kur nurodžiau koks rezultatas turėtų būti..
c) šiuo atveju negalima atlikti jokių normalizavimų;

Dar šiek tiek pasikankinęs ir panaudojęs LEFT JOIN susikūriau užklausą, kuri daro:
1) išrenka klientus, kurie priklauso vadybininkui;
2) išrenka klientus, kurie priklauso adminui;
3) sujungia abu rezultatus;

o palyginti kompanijų nepavyksta niekaip :( žemiau užklausa.


SELECT `lead_main`.`company`
 
FROM  ((`lead` AS `lead_main`


LEFT JOIN `lead` AS `lead_vadybininkas` ON `lead_vadybininkas`.`leadid` = `lead_main`.`leadid`

LEFT JOIN `entity` AS `entity_vadybininkas` ON `entity_vadybininkas`.`leadid` = `lead_main`.`leadid`

LEFT JOIN `users` AS `users_vadybininkas` ON `users_vadybininkas`.`id` = `entity_vadybininkas`.`id` AND `users_vadybininkas`.`name` = 'vadybininkas')



LEFT JOIN `lead` AS `lead_admin` ON `lead_admin`.`leadid` = `lead_main`.`leadid`

LEFT JOIN `entity` AS `entity_admin`  ON `entity_admin`.`leadid` = `lead_admin`.`leadid`

LEFT JOIN `users` AS `users_admin` ON `users_admin`.`id` = `entity_admin`.`userid` AND `users_admin`.`name` = 'admin')


WHERE     `users_admin`.`name` = 'admin'

Kad palyginti kompanijas bandžau sąlygoje prikabinti kažką tokio:

`lead_admin`.`company` = `lead_vadybininkas`.`company`

arba konstruoti ORDER BY bet kažkodėl nelygina lyg užsispyręs :)
įtariu kad galbūt šiuo atveju trūksta kažkokios teisingos ORDER BY išraiškos....

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Nežinau, pabandyk prisitaikyt:

SELECT lead_admino.leadid,
  lead_admino.company
FROM entity
  LEFT JOIN lead AS lead_admino ON entity.leadid = lead_admino.leadid
    AND entity.userid = 1
  LEFT JOIN lead AS lead_vadybininko ON entity.leadid = lead_vadybininko.leadid
    AND entity.userid = 2
WHERE lead_admino.company = lead_vadybininko.company
  AND lead_vadybininko.company IS NOT NULL

8 (edited by Ramex 2008-10-08 20:32:15)

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Užklausa turi išvesti tuos klientus, kurie priklauso darbuotojui 'admin'. Priklauso darbuotojui 'admin' REIšKIA, kad klientų, priklausančių darbuotojui 'admin' ir darbuotojui 'vadybininkas', 'company' lauko reikšmės yra VIENODOS.

kad ir kiek skaičiau, niekaip nesupratau. čia gaunasi maždaug taip: "man reikia sužinoti, kurios duonos riekelės yra sviestuotos. Sviestuotos reiškia, kad jos yra sviestuotos ir trupiniuotos, riekelės netinkamos valgyti." na po velnių, jei nesugebam regst savo minčių, tai kaip galime tikėtis pagalbos. nesinori pamokslauti, bet sąvokos neįmanoma paaiškinti, jei ji tiesiogiai naudojama paaiškinime, šiuo atveju "priklauso adminui". tai jei tu dar kartą pabandytum paaiškinti, ką būtent reiškia minėtasis apibrėžimas, nes mano suvokimu tavo apibrėžimas yra visiška priešingybė tavo pateiktiem rezultatam, tai gal ir gautum tikslesnį atsakymą.

Su sąlyga, kad šūdo nebus...

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Labas rytas,
kartoju, jei šis išsireiškimas nieko nesako:

Užklausa turi išvesti tuos klientus, kurie priklauso darbuotojui 'admin'. Priklauso darbuotojui 'admin' REIšKIA, kad klientų, priklausančių darbuotojui 'admin' ir darbuotojui 'vadybininkas', 'company' lauko reikšmės yra VIENODOS.

nekreipki į ji dėmesio.
Tiksliai ko man reikia yra nurodyta pirmoje mano žinutėje

užklausos rezultatas turėtų būti:

leadid    company
7             niekadejas

O lentelės su tiksliais duomenimis pateikta žemiau.

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Tai mano pateikta užklausa netiko?

11 (edited by minius 2008-10-09 08:05:51)

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

šiaip tavo pasiūlyta užklausa panaši į mano, tik jungiama prie kitos lentelės. Bet ji neišveda jokio rezultato, nepavyko pritaikyti.

12 (edited by minde 2008-10-09 09:58:50)

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

minius wrote:

Dar šiek tiek pasikankinęs ir panaudojęs LEFT JOIN susikūriau užklausą, kuri daro:
1) išrenka klientus, kurie priklauso vadybininkui;
2) išrenka klientus, kurie priklauso adminui;
3) sujungia abu rezultatus;

Man tai gaunasi taip:

SELECT admino.leadid, admino.company
FROM (SELECT leadid, company FROM entity LEFT JOIN lead ON lead_id = leadid AND user_id = 1) AS admino
  INNER JOIN (SELECT leadid, company FROM entity LEFT JOIN lead ON lead_id = leadid AND user_id = 2) AS vadybininko
    ON admino.company = vadybininko.company

Bet kaip matai, rezultatai neteisingi, nes arba tu blogai patekei duomenis arba rezultatus arba tavo pateiktos taisyklės yra nevienareikšmiškos...

... arba mano užklausa bloga (-;

13 (edited by minius 2008-10-09 10:04:33)

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Mano pateikti pirminiai duomenys ir reikiamas rezultatas yra teisingai suformuluoti.

Neįvertinta tiesiog viena sąlyga, kurią minėjau pirmoje savo žinioje, kad įrašų skaičius lentelėje yra apie 60 000.

Todėl bet kokios užklausos kurios turi subužklausas, ar kažkokias IN išraiškas yra tiesiog nebaigiamos vykdyti.

Dėl to aš ir bandžiau visai parašyti užklausą per JOIN'nus, nes jie greitai veikia. Tai šiuo atveju geriausias sprendimas būtų SELECT'as tik su JOIN'ais ir naudojant WHERE paprastai be jokių subužklausų.

Manau, tikrai galima tokią parašyti, tik neįkertu kaip. Laikas spaudžia.


Sugalvojau daryt kitaip. Kursiu laikiną lentelę su vadybininkui priklausančiais klientais ir paskui per kitą užklausą palyginsiu.

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

a) 60000 įrašų nėra DAUG;
b) norint šitą uždavinį išspręsti tik su JOIN'ais reikia pirmiausia turėti teisingą duomenų schemą;
c) nereikia lygint subužklausos, kuri vykdoma N kartų (tiek, kiek yra įrašų rezultate) ir yra talpinama pvz SELECT stulpelių sąraše, su ta, kuri vykdoma tik vieną karta ir yra naudojama sujungiant; aišku šiuo atveju prarandami pranašumai sujungtinėti pagal indeksus (nors aš stipriai abejoju ar jie pas tave iš vis yra, ypač ant stulpelio company);

Gali pabandyti pažiūrėti, užklausos, kuri pagal viską grąžina pirminius duomenis, kuriems pritaikius GROUP/WHERE/kažka kita turėtum gauti rezultatus, kodą:

SELECT *
FROM entity
  LEFT JOIN lead AS lead_admino ON entity.lead_id = lead_admino.leadid
    AND entity.user_id = 1
  LEFT JOIN lead AS lead_vadybininko ON entity.lead_id = lead_vadybininko.leadid
    AND entity.user_id = 2

čia supaprastintas variantas, tos užklausos kurią pateikiau pirmiausia. Pažiūrėjęs į duomenis suprasi, kad nėra jokių būdų išrinkti rezultatus, nes jie tarpusavyje neturi jokio ryšio, kurį galėtum aprašyti be subužklausų. Vienintelis sprendimas prie turimų aplinkybių yra tie trys algoritmo punktai, kuriuos patekiau anksčiau - bet kad juos įvykdyti turi jungti dvi rezultatų aibes (vadybininko ir admino) per company stulpelį.

Tai pradžiai tiek (-;

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

Pasidariau su laikina lentele - paprasčiau ir greičiau ;)

Dėkui už patarimus

Re: Sudėtingesnė SELECT užklausa naudojant JOIN sintaksę

O tu supranti, kad "duomenys -> laikina lentelė -> rezultatai" mažai kuo skiriasi nuo subužklausų? Subužklausos rezultatai laikinai yra saugomi leikinoje lentelėje (-;

Tai gal tiesiog reikėjo padaryti VIEW'ą ir viskas. Dar paprasčiau, greičiau (-;