Hulp bij SELECT en count...

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Nanno Koerts

Nanno Koerts

08/02/2022 00:43:21
Quote Anchor link
Ik heb hulp nodig bij het optellen van waarden uit de mySql database, maar ik lees dat ik hier geen script request mag doen en het is mij niet duidelijk waar ik dat dan wel mag doen.
Ik ben geen volleerd programmeur en heb enkel de basis een beetje onder de knie.
Wie wil mij helpen?

Groet,

Nanno
 
PHP hulp

PHP hulp

21/11/2024 21:28:40
 
- Ariën  -
Beheerder

- Ariën -

08/02/2022 01:04:02
Quote Anchor link
Scripts request horen niet in het 'gezocht' forum. Dit is het 'Algemene PHP scripting en meer' waar het gewoon mag.

Maar optellen met MySQL is niet echt heel moeilijk.
Kijk eens naar de SUM() functie:

https://www.w3schools.com/sql/func_mysql_sum.asp
 
Nanno Koerts

Nanno Koerts

08/02/2022 03:11:40
Quote Anchor link
Hoi Arien,

Er stond in de info dat ik geen script request mocht doen, maar ik begrijp dat je me hier dus wel wil en kan helpen.

Het gaat niet enkel om 1 ding op te tellen. Ik heb ook al zitten stoeien met COUNT, maar ik raak helemaal in de war door de manier van filteren. Hoe ik dit in mijn string plaats...

Ik heb de tabel Kaarten en de kolommen 'Voorstelling_id', 'Aantal_Kaarten' en 'Betaald_kenmerk'.

Nu wil ik alle kaarten tellen die Voorstelling_id: 1 hebben en met het Betaald_kenmerk: KP.
Dit is mijn poging van mijn code. Het aantal KP weergeeft hij goed, maar het aantal kaarten blijft nul.
Wil je me helpen dit logisch te maken?

$totaal_KP_kaarten = 0;

$resultaat_KP = mysqli_query($connect_agenda, "SELECT COUNT(Aantal_Kaarten) FROM Kaarten WHERE Voorstelling_id = $artiest_id AND Betaald_kenmerk = 'KP' AND Crediteer='Nee'");

while ($row_KP = mysqli_fetch_array($resultaat_KP))
{
$totaal_KP = mysqli_num_rows($resultaat_KP);
$totaal_KP_kaarten = $totaal_KP_kaarten + $row_KP['Aantal_Kaarten'];
}
echo'
 
Ivo P

Ivo P

08/02/2022 08:55:05
Quote Anchor link
Om te beginnen de verwarring: in het Nederlands heb je "tellen" en "optellen".

Tellen doe je met bijvoorbeeld auto's: hoeveel auto's rijden er dit uur door de straat?
Dat is steeds +1 op het moment dat er eentje langsrijdt.

Maar optellen doe je met het aantal inzittenden: 1 + 1+ 4 + 4 etc

Of in database termen: Tellen doe je met het aantal records
optellen met de inhoud van een (numerieke) kolom

Engels: tellen >> count; optellen >> sum
Zo te zien heb jij hier sum nodig

De query zou moeten zijn:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
SELECT
   SUM(Aantal_Kaarten) AS aantal
FROM Kaarten
WHERE Voorstelling_id = $artiest_id
  AND Betaald_kenmerk = 'KP'
  AND Crediteer='Nee'


mysqli_num_rows() zal altijd 1 zijn: je krijgt immers 1 getal terug (de sommatie)
Die sommatie kan 100 zijn, 89 of misschien wel 0.
Maar het is altijd 1 getal.

Ik heb hierboven een alias gebruikt : AS aantal

Dat betekent dat je middels een fetch() functie een kolom in PHP kunt verwachten met de naam "aantal"

In jouw geval had je $row_KP[0] misschien kunnen gebruiken, of $row_KP['COUNT(Aantal_Kaarten)'] Maar dat is over het algemeen niet handig: een alias is handiger,
maar dan nog klopte je query niet.

En daar komt de alias weer om de hoek: als je achteraf de query aanpast wil je niet je hele code doorlopen om de betreffende functie-aanroep in allerlei array-indexes ook aan te passen.
 
Nanno Koerts

Nanno Koerts

08/02/2022 16:26:05
Quote Anchor link
Whow, mooie en lange uitleg.

Nou snap ik inderdaad waar ik door in de war raak, optellen en tellen, daar gaat het in mijn hoofd fout.

En daar zit dus ook de uitdaging, ik wil de aantal kaarten optellen en het aantal KP tellen.

Kan ik dit in 1 query of doe ik dit in 2?
Deze code heeft geen invloed op de rest van het script. Ik heb een pagina met een overzicht van het aantal reserveringen voor een voorstelling.
Dus in de database Kaarten staan alle bestellingen.

Pietje heeft id 1 en heeft 4 kaarten besteld voor voorstelling_id 12 en hij betaald met pin (KP).
Klaasje heeft id 2 en heeft 6 kaarten besteld voor voorstelling_id 12 en hij betaald contant(KC).
Jantje heeft id 3 en heeft 2 kaarten besteld voor voorstelling_id 12 en hij betaald met pin (KP).

Nu wil ik dus het resultaat hebben van het aantal kaarten die gepind zijn.
Dus 2 x KP = 6 kaarten.

Dit is wat ik probeerde te doen.
Het gekke is dat de numrows wel het aantal KP (Betaald_kenmerk) juist wist te tellen.

Wil je hier nog eens naar kijken voor me of de code dan van toepassing is?
In ieder geval bedankt voor je uitgebreide reactie.
 
Adoptive Solution

Adoptive Solution

08/02/2022 16:49:53
Quote Anchor link
Zes jaar geleden vroeg je iets vergelijkbaars.
https://www.phphulp.nl/php/forum/topic/optellen-in-mysql-database/99949/
Ik heb het voorbeeld wat uitgebreid met deze mysql data:

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
29
30
31
32
33
34
35
36
37
38
39
40
DROP TABLE IF EXISTS `kaartjes`;
CREATE TABLE `kaartjes` (
  `klant_id` int(10) NOT NULL AUTO_INCREMENT,
  `klant_naam` varchar(100) NOT NULL,
  `klant_aantal` int(10) NOT NULL,
  `prijs` decimal(5,2) NOT NULL,
  `Voorstelling_id` int(10) NOT NULL,
  `Betaald_kenmerk` char(5) NOT NULL,
  `Crediteer` char(5) NOT NULL,
  PRIMARY KEY (`klant_id`),
  UNIQUE KEY `klant_id` (`klant_id`),
  KEY `klant_naam` (`klant_naam`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `kaartjes` (`klant_id`, `klant_naam`, `klant_aantal`, `prijs`, `Voorstelling_id`, `Betaald_kenmerk`, `Crediteer`) VALUES
(1,    'Jansen, G.J',    2,    7.00,    1,    'KP',    'Nee'),
(2,    'Klaveren, K. van',    3,    9.50,    1,    'KC',    'Ja'),
(3,    'Pietersen, M.',    5,    10.00,    2,    'KP',    'Nee'),
(4,    'Zegwaard, K.L. van',    3,    10.00,    2,    'KC',    'Ja'),
(5,    'Rompaai, Jan van',    2,    10.00,    2,    'KP',    'Nee'),
(6,    'Zegwaard, K.L. van',    2,    25.00,    7,    'KL',    'Nee');


SELECT * FROM kaartjes;

SELECT klant_id,
klant_naam ,
prijs,
COALESCE( SUM(klant_aantal), 0) AS aantal,
COALESCE( SUM(klant_aantal * prijs ), 0 ) AS totaal,
Voorstelling_id,
Betaald_kenmerk,
Crediteer
FROM kaartjes WHERE Voorstelling_id <> 0
GROUP BY Voorstelling_id, klant_id
ORDER BY klant_naam ASC, Voorstelling_id;

SELECT Betaald_kenmerk AS kenmerk, SUM(klant_aantal ) AS aantal FROM kaartjes WHERE Betaald_kenmerk = 'KP';

SELECT Betaald_kenmerk AS kenmerk, SUM(klant_aantal ) AS aantal FROM kaartjes GROUP BY Betaald_kenmerk;


Toevoeging op 08/02/2022 16:52:56:

En voor het gemak een webpagina.
Het connect.php bestand maakt een verbinding met new mysqli();
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<!DOCTYPE HTML>

<html>

<head>

<title>Kaartjes</title>

<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />

<meta name="viewport" content="user-scalable=1, width=device-width, initial-scale=1.0, maximum-scale=2.0, minimum-scale=1.0" />

<style>
html {
    font-size: 13px;
    }
body:before {
    content: "";
    position: fixed;
    top: -10px;
    left: 0px;
    width: 100%;
    height: 10px;
    z-index: 100;
    -webkit-box-shadow: 0px 0px 10px rgba(0,0,0,.8);
    -moz-box-shadow: 0px 0px 10px rgba(0,0,0,.8);
    box-shadow: 0px 0px 10px rgba(0,0,0,.8);
}

div#container {
    font-family: Futura;
    font-size: 1.0em;
    max-width: 550px;
    border: 0.100em solid red;
    padding: 1.000em;
    margin: 1.000em auto;
    background-color: ivory;
    -webkit-box-shadow: 0px 0px 10px rgba(0,0,0,.8);
    -moz-box-shadow: 0px 0px 10px rgba(0,0,0,.8);
    box-shadow: 0px 0px 10px rgba(0,0,0,.8);
}
table, th, td {
    border: 0.100em solid navy;
    border-collapse: collapse;
    }

table {
    width: 100%;
    }

th {
    text-align: left;
    background-color: #dcdc00;
    }

th, td {
    padding: 0.500em;
    }

tr:nth-child(odd) {
    background: #dcdcdc;
    }

tr:nth-child(even) {
    background: #dcdcaa;
    }

tr.footer {
    background: #dcdc00;
    }
tr.footer td:nth-child(3),
tr.footer td:nth-child(4) {border-top: 0.300em solid navy !important;}

td.right {text-align: right;}
</style>
</head>

<body>

<div id="container">

<h2>Kaartverkoop</h2>

<table style="border:0.100em solid red;width:100%;">

<thead>
    <tr>
        <th style="text-align: left;">Klant</th>
        <th style="text-align: right;">Prijs</th>
        <th style="text-align: right;">Aantal</th>
        <th style="text-align: right;">Totaal</th>
        <th>Voorstelling</th>
        <th>Betaald</th>
        <th>Crediteer</th>
    </tr>
</thead>

<?php

include ('connect.php');
if ( $db_result )
{

    $query = "SELECT klant_id,
    klant_naam ,
    prijs,
    COALESCE( SUM(klant_aantal), 0) AS aantal,
    COALESCE( SUM(klant_aantal * prijs ), 0 ) AS totaal,
    Voorstelling_id,
    Betaald_kenmerk,
    Crediteer
    FROM kaartjes WHERE Voorstelling_id <> 0
    GROUP BY Voorstelling_id, klant_id
    ORDER BY klant_naam ASC, Voorstelling_id;"
;

    if ( $result = $db->query( $query ) )
    {

        while( $row = $result->fetch_object() )
        {

        ?>

        <tr>
            <td><?php echo $row->klant_naam; ?></td>
            <td style='text-align: right;'><?php echo $row->prijs; ?></td>
            <td class='right'><?php echo $row->aantal; ?></td>
            <td class='right'><?php echo $row->totaal; ?></td>
            <td class='right'><?php echo $row->Voorstelling_id; ?></td>
            <td class='right'><?php echo $row->Betaald_kenmerk; ?></td>
            <td class='right'><?php echo $row->Crediteer; ?></td>
        </tr>
        <?php
        }
    }


    $query = "SELECT
    SUM(klant_aantal) AS aantal,
    SUM(klant_aantal * prijs) AS totaal
    FROM kaartjes WHERE Voorstelling_id <> 0;"
;

    if ( $result = $db->query( $query ) )
    {

        while( $row = $result->fetch_object() )
        {

        ?>

        <tr class='footer'>
            <td>Totaal</td>
            <td></td>
            <td class='right'><?php echo $row->aantal; ?></td>
            <td class='right'><?php echo $row->totaal; ?></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <?php
        }
    }
}

?>

</table>

</div>

</body>

</html>
 
Ivo P

Ivo P

08/02/2022 16:58:31
Quote Anchor link
@Adoptive:
op regel 35 missen wat kolommen in de group-by: daar moeten alle kolommen die geen SUM/COUNT etc bevatten genoemd worden.

dus GROUP BY klant_id, klant_naam, prijs, voorstelling_id, Betaald_kenmerk, Crediteer

Het ophalen van alle betaaldata kán in 1 query.
De vraag is, of je dat wilt.
Als je alleen de printransacties wilt hebben, dan heeft het ophalen en groupby-en op transactiesoort geen zin.
Maar als je wilt weten dat er 35 tickets verkocht zijn (voor het aantal stoelen) is het minder interessant dat Piet er 4 besteld heeft en Janneke 2.
 
Nanno Koerts

Nanno Koerts

08/02/2022 17:56:16
Quote Anchor link
@Ivo

Ik heb dat overzicht al van de namen en aantal kaartjes met daaronder opgeteld het totaal aantal kaarten voor die voorstelling.

Voor de boekhouder wil ik op die pagina een beknopt overzicht erbij plaatsen hoeveel kaarten er gepind zijn, en hoeveel er contant zijn betaald.

Ik ga hier eens even mee stoeien, denk dat ik het nu beter begrijp.

@Adoptive

Tof dat je me hier zo uitgebreid mee helpt. Ja ik vroeg dat jaren geleden ook en bemerk dat ik moeite heb met rekenen. Die hersenen snappen het dan niet en zag inderdaad het verschil niet in tellen en optellen. Dat nu wetende maakt het al een stuk eenvoudiger.

Toevoeging op 08/02/2022 18:05:44:

Afbeelding
 
Ivo P

Ivo P

08/02/2022 18:28:16
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
SELECT
   SUM(Aantal_Kaarten) AS totaalaantal,
   Betaald_kenmerk
FROM Kaarten
GROUP BY
   Betaald_kenmerk
WHERE
   Voorstelling_id = 123


Dat zou iets opleveren als
4 PIN
28 CASH
3 Creditcard

Maar dat is dus niet te combineren met wíe heeft dan 4 en 8 kaarten gekocht.
 
Nanno Koerts

Nanno Koerts

08/02/2022 19:24:30
Quote Anchor link
@Ivo en Adoptive

Ik ben eruit... Ik moest even in mijn hoofd afstand doen en omschakelen.
Dank voor jullie hulp!!!


Ik heb nu deze code:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
<?
    $resultaat_KP
= mysqli_query($connect_agenda, "SELECT Betaald_kenmerk AS kenmerk, SUM(Aantal_Kaarten) AS aantal, COUNT(Betaald_kenmerk) AS kenmerk_aantal FROM Kaarten WHERE Betaald_kenmerk = 'KP' AND Crediteer='Nee'");

    while ($row_KP = mysqli_fetch_object($resultaat_KP))
        {

        $totaal_KP_kenmerk = $row_KP->kenmerk;
        $totaal_KP = $row_KP->kenmerk_aantal;
        $totaal_KP_kaarten = $row_KP->aantal;
        }


echo'Totaal kaarten via Pin: '.$totaal_KP_kaarten.' ('.$totaal_KP_kenmerk.')  Aantal pinbetalingen: '.$totaal_KP.'';
?>


Met dit als resultaat:
Afbeelding
 
Ivo P

Ivo P

08/02/2022 19:29:16
Quote Anchor link
nee.

Je mist group by in je query.
Dat geeft met beroerd ingestelde Mysql servers weliswaar geen foutmelding, maar wel min of meer random resultaten.

In dit geval valt dat niet op, omdat je maar 1 kenmerk hebt: die staat in de WHERE.
Maar als je er WHERE Betaald_Kenmerk IN ('KP', 'KC')
van maakt, dan ben ik benieuwd hoe dan de getallen erbij verschijnen.
(dus zonder group-by geen losse kolommen selecteren, of de losse kolommen in je group-by opnemen)

Ik heb ooit een stuk hierover geschreven:
https://www.phphulp.nl/php/tutorial/databases/group-by/846/
 
Nanno Koerts

Nanno Koerts

08/02/2022 19:39:39
Quote Anchor link
Ik snap je toelichting, maar ik ga straks de andere 3 kenmerken apart vermelden. Dus bedacht met dat ik gewoon de code 3 keer herhaal, dan kan het niet fout gaan lijkt mij... toch?
En als het wel een noodzaak is, doe ik dan GROUP BY Betaald_kenmerk?

Ik heb die straks wel nodig bij het groeperen van de reserveringsnummers, want 1 reserveringsnummer bevat meerdere voorstellingen en dus meerdere kaarten.
 
Ivo P

Ivo P

08/02/2022 19:45:31
Quote Anchor link
ja: als er aggregatie-functies gebruikt worden, zoals sum(), count(), avg(), group_concat(), Max(), min() etc
dan moeten alle kolommen die je los vermeldt in het select-deel in het group-by stuk staan.

En op zich snap ik de redenering "als ik 3 losse query's doe en ik heb maar 1 voorkomende waarde in die kolom, dan klopt het resultaat evengoed".

Maar dan komt er over 2 jaar een update van je database.
- opgelegd door je hoster
- omdat er een mega security-issue is
- omdat je verhuist naar een nieuwe server
- etc

En dan zit je ineens met 25 plekken waar je query's tot een foutmelding leiden. En met een beetje pech nog op zo'n manier dat je alleen geen resultaten ziet maar niet de reden van het mislukken.
En dan moet je het dán oplossen.
Terwijl je het nu ook direct goed kunt doen.
 
Nanno Koerts

Nanno Koerts

08/02/2022 20:09:33
Quote Anchor link
Ik snap geheel wat je schrijft... 1 jan 2022 heb ik dit gemerkt. De website liep geheel in de soep door al mijn gemaakte fouten in het script en liep nog ergens in versie 4. Ik ben nu een geheel nieuwe website aan het bouwen met zo goed als mogelijk de juiste code. Met versie 8 ondervind ik gelukkig nog geen problemen.

Ik krijg wel een error als ik nu Group by erbij voeg tussen FROM en WHERE. Ik ben gewend dat deze altijd aan het einde van de select deel staat. En als ik die aan het einde erbij plaats doet de code het wel.

Klopt dat?
 
Ramon van Dongen

Ramon van Dongen

09/02/2022 11:15:19
Quote Anchor link
Hallo Nanno

Hier zie je precies de volgorde van de SELECT syntax;
https://dev.mysql.com/doc/refman/8.0/en/select.html

Dus in jouw geval;
1) SELECT
2) FROM
3) WHERE
4) GROUP BY
 
Nanno Koerts

Nanno Koerts

09/02/2022 12:34:34
Quote Anchor link
Thanks Ramon!!!!
 



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.