Mysql Twee Counts geven dezelfde resultaat

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Francoi gckx

Francoi gckx

17/02/2014 12:29:51
Quote Anchor link
Ik heb in 'beheer_solicitaties bsol' 2 rows
en in 'beheer_notities bn' maar 1
Toch geeft hij bij beide counts 2, waarom?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
SELECT
            SQL_CALC_FOUND_ROWS bv.bv_id,        
            bv.ba_id,
            COUNT(bn.bn_notitie) as bn_aantal,
            COUNT(bsol.bsol_motivatie) as bsol_aantal
            FROM beheer_vacatures bv
            LEFT JOIN beheer_solicitaties bsol
            ON  bv.bv_id = bsol.bv_id
            LEFT JOIN beheer_notities bn
            ON bv.bv_id = bn.bv_id
            GROUP BY
                bv.bv_id
 
PHP hulp

PHP hulp

21/12/2024 13:29:47
 
Ger van Steenderen
Tutorial mod

Ger van Steenderen

17/02/2014 15:53:01
Quote Anchor link
Omdat JOINS zo werken, sterker nog als het bv resp 3 en 2 rijen zouden zijn dan krijg je als resultaat 6.
Dit kan je alleen maar verhelpen door het tellen in een subquery te doen, i.e:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
..........
LEFT JOIN
    (SELECT bv_id, COUNT(*) bssol_aantal
    FROM beheer_solicitaties
    GROUP BY bv_id) bsol
     ON  bv.bv_id = bsol.bv_id
LEFT JOIN
    /* de volgende subquery */

En let op dat als je met SQL_CALC_FOUND_ROWS werkt, dit vaker (aanzienlijk) langzamer is dan twee queries (één voor het result met de limit en één met SELECT count(*) voor het totaal aantal)
 
Francoi gckx

Francoi gckx

17/02/2014 16:17:57
Quote Anchor link
Ik heb de query aangepast en het is nu wat ik wil, danke.

Ik gebruik SQL_CALC_FOUND_ROWS om vooraf te bepalen hoeveel results er altijd totaal zijn.
Dan fetch ik dat:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
$total = $this->db->query("SELECT FOUND_ROWS()");
                    $rowTotal = $total->fetch();
                    $total_results = $rowTotal['FOUND_ROWS()'];
                    $arrayed = $query->fetchAll();
                    $arrayed['total_results'] = $total_results;


Dan met php en als iemand 10 of 100 tegelijk wil op de pagina dan doe ik dat met $per_page
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
$total_results = $vacatures['total_results'];
$total_pages = ceil($total_results / $per_page);


In hoeverre is dit langzamer moet ik dit stukje onder dan vervangen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
SELECT SQL_CALC_FOUND_ROWS bv.bv_id


Naar SELECT COUNT(bv.bv_id) as total_results, volgende_columns..

waarom is er dan uberhaupt SQL_CALC_FOUND_ROWS?
Gewijzigd op 17/02/2014 16:18:56 door Francoi gckx
 
Ger van Steenderen
Tutorial mod

Ger van Steenderen

17/02/2014 17:21:20
Quote Anchor link
Op die laatste vraag kan ik geen (zinnig) antwoord geven.

Het levert in ieder geval maar zelden voordeel, omdat sql_calc_found_rows altijd een full tablescan tot gevolg heeft. Dit is niet het geval als je met SELECT count(*) FROM .... WHERE .... als de kolom(men) in de WHERE een index heeft (hebben).
In jouw geval werk je ook nog eens met group_by en left join dus kan je veel beter het aantal vacuteres bepalen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
SELECT COUNT(*) totaal FROM beheer_vacatures

En het dan uit de andere query SQL_CALC_FOUND_ROWS gewoon weglaten
 
Francoi gckx

Francoi gckx

17/02/2014 20:28:59
Quote Anchor link
Ik leer echt veel van je!

Moet ik voor de volgende situatie ook een sub query gebruiken?

Ik wil maar 1 vacature gegevens laten zien met daar onder al zijn solicitaties
Zonder subquery en alleen met left join en alle select data in het begin;
Krijg ik met een vacature die 2 solicitaties heeft ook 2 keer dezelfde vacature gegevens. Nu zou dit wel met PHP oplosbaar te zijn. Maar toch als we toch over efficientie hebben.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SELECT
            
            bsol.bsol_naam,
            bsol.bsol_email,
            bsol.bsol_motivatie,
            bsol.bsol_cvlink,
            bsol.bsol_datum,
            bsol.bsol_id,
            ba_woonplaats,
            bb.bb_bedrijfsnaam
            FROM beheer_solicitaties bsol
            LEFT JOIN beheer_bedrijven bb
            ON bb.ba_id = bsol.ba_id
            LEFT JOIN (SELECT DISTINCT bv_id, bv_beschrijving,
            bv_functie,
            bv_plaats,
            bv_categorie, bv_beschikbaar,
            bv_ervaring,
            bv_datum,            
            ba_id,
            bv_datum_gewijzigd
            FROM beheer_vacatures
            GROUP BY bv_id) bv
            ON  bsol.bv_id = bv.bv_id    
            LEFT JOIN beheer_accounts ba
            ON  bsol.ba_id = ba.ba_id                
            WHERE bv.bv_id = 7
            ORDER BY bsol.bsol_id


Het geeft geen foutmelding maar het lijkt er op dat hij alles in de subquery select negeert:/
 
Ger van Steenderen
Tutorial mod

Ger van Steenderen

17/02/2014 21:18:56
Quote Anchor link
>>Ik wil maar 1 vacature gegevens laten zien met daar onder al zijn solicitaties
Let op de volgorde waarin je de selecteert, je begint met "ik wil 1 vacature" maar in de from heb je de sollicitaties tabel en daarachter een left join
Probeer een query op dezelfde manier op te bouwen zoals je de vraag stelt, dus geef mij de sollicaties die bij een vacature horen resulteert in
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
SELECT ....
FROM beheer_vacatures bv

In jouw voorbeeld selecteer je eesrt alle sollicitaties en daarna ga je kijken of er eventueel een vacature bij hoort.
 
Francoi gckx

Francoi gckx

17/02/2014 21:41:39
Quote Anchor link
Met geen goede rede had ik het omgedraaid in een van de pogingen om de query goed te krijgen.

Ik heb het nu omgedraaid een subquery er ingebouwd maar klopt het dat een
lijst van geselecteerde items in een sub query iets extraas nodig heeft om opgenomen te worden
in een tabel dan? Hij doet namelijk niks met de lijst van geselecteerde items in de subquery.
Hij geeft als het ware alleen de vacature weer met zn gegevens

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SELECT
            bv.bv_beschrijving,
            bv.bv_functie,
            bv.bv_plaats,
            bv.bv_categorie, bv.bv_beschikbaar,
            bv.bv_ervaring,
            bv.bv_datum,            
            bv.ba_id,
            bv_datum_gewijzigd,
            ba_woonplaats,
            bb.bb_bedrijfsnaam
            FROM beheer_vacatures bv
LEFT JOIN (SELECT bv_id, bsol_naam,
            bsol_email,
            bsol_motivatie,
            bsol_cvlink,
            bsol_datum,
            bsol_id,
ba_id
    FROM beheer_solicitaties
    GROUP BY bv_id) as bsol
     ON  bv.bv_id = bsol.bv_id                            
            WHERE bv.bv_id = 7
            
 
Ger van Steenderen
Tutorial mod

Ger van Steenderen

17/02/2014 21:53:01
Quote Anchor link
Heb je de subquery als eens goed bekeken?:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
(SELECT bv_id, bsol_naam,
            bsol_email,
            bsol_motivatie,
            bsol_cvlink,
            bsol_datum,
            bsol_id,
ba_id
    FROM beheer_solicitaties
    GROUP BY bv_id)

Een vage group by, daar hebben we het pas nog over gehad ;-)
Gewijzigd op 17/02/2014 21:53:40 door Ger van Steenderen
 
Francoi gckx

Francoi gckx

17/02/2014 21:58:24
Quote Anchor link
Ja er is geen aggraat functie in heel de query dus geen group by nodig right;)?

Zonder group by krijg ik 1 vacature maar dan ook alleen de vacature gegevens.
Met krijg ik maar liefst twee vacatures, dezelfde, maar dan ook alleen de vacature gegevens.

Ik denk dat ik DISTINCT nodig heb op de beheer_vacatures en dan hoe worden de subquery items opgenomen?
 
Ger van Steenderen
Tutorial mod

Ger van Steenderen

17/02/2014 22:10:20
Quote Anchor link
Gooi het een beetje uit elkaar, als je het over één vacature hebt is er helemaal niks mee om dit in 2 query's te doen.
Dus eerst de algemene info ophalen, en dan de bij behorende sollicitaties, ik denk dat je het jezelf daar een stuk makkelijker mee maakt.
 
Francoi gckx

Francoi gckx

17/02/2014 22:17:52
Quote Anchor link
Ok dan doe ik dat hoor, hoort geen probleem te zijn!

Toch uit nieuwsgierigheid had het wel gekund?
Of wordt de query dan groter dan de twee afzonderlijke queries naast elkaar en met meer toeters en bellen :)?
 
Ger van Steenderen
Tutorial mod

Ger van Steenderen

18/02/2014 16:25:55
Quote Anchor link
Het kan beide.
Met één query wordt de algemene data een x aantal maal herhaald, terwijl je hem maar één maal nodig hebt.

Daar tegen over een extra query.

Maakt het veel verschil in performance? Niet noemenswaardig.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.