Ik krijg niet wat ik wil hebben met Mysql
Nu ben ik al een tijdje het volgende aan het proberen met een script:
Code (php)
1
2
3
2
3
$kasquery = "and `date` like <= '".$_POST['jaar']."".$maand3."%'";
$query = "SELECT type, SUM(bedrag) FROM factuur_betalingen WHERE `afbij` = 'BIJ' AND (`type` = 'OVERSCHRIJVING' OR `type` = 'IDEAL' OR `type` = 'PIN') ".$kasquery." GROUP BY type";
$result = mysqli_query($link,$query) or die(mysqli_error());
$query = "SELECT type, SUM(bedrag) FROM factuur_betalingen WHERE `afbij` = 'BIJ' AND (`type` = 'OVERSCHRIJVING' OR `type` = 'IDEAL' OR `type` = 'PIN') ".$kasquery." GROUP BY type";
$result = mysqli_query($link,$query) or die(mysqli_error());
Nu wil ik dus dat hij zoekt onder bijvoorbeeld 202203% of gelijk aan 202203%
Zoals ik hem nu ingevoerd heb werkt het niet, als ik het zo doe:
Code (php)
1
2
3
2
3
$kasquery = "and `date` <= '".$_POST['jaar']."".$maand3."%'";
$query = "SELECT type, SUM(bedrag) FROM factuur_betalingen WHERE `afbij` = 'BIJ' AND (`type` = 'OVERSCHRIJVING' OR `type` = 'IDEAL' OR `type` = 'PIN') ".$kasquery." GROUP BY type";
$result = mysqli_query($link,$query) or die(mysqli_error());
$query = "SELECT type, SUM(bedrag) FROM factuur_betalingen WHERE `afbij` = 'BIJ' AND (`type` = 'OVERSCHRIJVING' OR `type` = 'IDEAL' OR `type` = 'PIN') ".$kasquery." GROUP BY type";
$result = mysqli_query($link,$query) or die(mysqli_error());
Neemt hij het niet tot de laatste mogelijkheid mee.
Heeft iemand een idee hoe ik dit werkend zal krijgen?
Alvast bedankt!
Enne... Je bent vatbaar voor (onbedoelde) SQL-injection wat ook voor hacking kan worden misbruikt.
- Ariën - op 04/03/2022 21:07:52:
Echo je hele query eens.
Enne... Je bent vatbaar voor (onbedoelde) SQL-injection wat ook voor hacking kan worden misbruikt.
Enne... Je bent vatbaar voor (onbedoelde) SQL-injection wat ook voor hacking kan worden misbruikt.
De query zit in een afgesloten gedeelte waar alleen ik bij kan, daarnaast is er vanuit de hostingprovider nog een en ander gedaan om injecties te voorkomen.
het lijkt hij laat bepaalde waarden weg waardoor de totaalstand niet klopt.
Je kan de sting van vandaag bijvoorbeeld zo zien: 20220304150311 daarvan hij alles pakken tot en met 202203 zolang het maar lager is dan 202204.
Maar als ik dus <= 202203% doe neemt hij niet alles uit de 202203% reeks mee.
Het enige wat mijn query doet is de waarden optellen:
Code (php)
1
2
3
2
3
while($row = mysqli_fetch_array($result)){
$inkomend = $inkomend + $row['SUM(bedrag)'];
}
$inkomend = $inkomend + $row['SUM(bedrag)'];
}
Aangezien de query niet "dood" gaat weet ik ook niet precies wat ik in de query fout heb staan.
Laat je hele query eens zien zoals die uitgevoerd wordt?
- Ariën - op 04/03/2022 21:49:03:
Een injection kan ook onwetend gebeuren, dus ALTIJD escapen.
Laat je hele query eens zien zoals die uitgevoerd wordt?
Laat je hele query eens zien zoals die uitgevoerd wordt?
dit is zoals hij staat hij telt waardes bij $inkomend en $uitgaand op.
Aan het einde van de rit hou ik dus $inkomend - $uitgaand over.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$kasquery = "and `date` <= '".$_POST['jaar']."".$maand3."%'";
$query = "SELECT type, SUM(bedrag) FROM factuur_betalingen WHERE `afbij` = 'BIJ' AND (`type` = 'OVERSCHRIJVING' OR `type` = 'IDEAL' OR `type` = 'PIN') ".$kasquery." GROUP BY type";
$result = mysqli_query($link,$query) or die(mysqli_error());
while($row = mysqli_fetch_array($result)){
$inkomend = $inkomend + $row['SUM(bedrag)'];
}
$query = "SELECT type, SUM(bedrag) FROM factuur_betalingen WHERE `afbij` = 'AF' AND (`type` = 'OVERSCHRIJVING') ".$kasquery."";
$result = mysqli_query($link,$query) or die(mysqli_error());
while($row = mysqli_fetch_array($result)){
$uitgaand = $uitgaand + $row['SUM(bedrag)'];
}
print "Resultaat: ".number_format($inkomend - $uitgaand,2);
$query = "SELECT type, SUM(bedrag) FROM factuur_betalingen WHERE `afbij` = 'BIJ' AND (`type` = 'OVERSCHRIJVING' OR `type` = 'IDEAL' OR `type` = 'PIN') ".$kasquery." GROUP BY type";
$result = mysqli_query($link,$query) or die(mysqli_error());
while($row = mysqli_fetch_array($result)){
$inkomend = $inkomend + $row['SUM(bedrag)'];
}
$query = "SELECT type, SUM(bedrag) FROM factuur_betalingen WHERE `afbij` = 'AF' AND (`type` = 'OVERSCHRIJVING') ".$kasquery."";
$result = mysqli_query($link,$query) or die(mysqli_error());
while($row = mysqli_fetch_array($result)){
$uitgaand = $uitgaand + $row['SUM(bedrag)'];
}
print "Resultaat: ".number_format($inkomend - $uitgaand,2);
dit staat boven de query:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if($_POST['kwartaal'] == '1e kwartaal'){
$maand1 = "01";
$maand2 = "02";
$maand3 = "03";
}
elseif($_POST['kwartaal'] == '2e kwartaal'){
$maand1 = "04";
$maand2 = "05";
$maand3 = "06";
}
elseif($_POST['kwartaal'] == '3e kwartaal'){
$maand1 = "07";
$maand2 = "08";
$maand3 = "09";
}
elseif($_POST['kwartaal'] == '4e kwartaal'){
$maand1 = "10";
$maand2 = "11";
$maand3 = "12";
}
$maand1 = "01";
$maand2 = "02";
$maand3 = "03";
}
elseif($_POST['kwartaal'] == '2e kwartaal'){
$maand1 = "04";
$maand2 = "05";
$maand3 = "06";
}
elseif($_POST['kwartaal'] == '3e kwartaal'){
$maand1 = "07";
$maand2 = "08";
$maand3 = "09";
}
elseif($_POST['kwartaal'] == '4e kwartaal'){
$maand1 = "10";
$maand2 = "11";
$maand3 = "12";
}
Op die basis wordt dus de maand bepaald, meer dan dat doet het script ook niet.
Het is dus vreemd dat hij in feite alleen dit ziet: "202003"
Ik zou op 2,055.28 moeten komen en ik kom op: 2,190.77
Het lijkt er op dat hij alles na 202203 niks meer mee neemt.
Toevoeging op 04/03/2022 22:18:24:
Trouwens, wat is de beste manier tegen injecties beschermen is dat toevallig: mysql_real_escape_string()?
Toevoeging op 04/03/2022 22:35:07:
Het zal hem trouwens uitgaand moeten zitten, als ik nareken is het uitgaande van de reeks 202203% niet mee genomen
Toevoeging op 04/03/2022 22:38:20:
Voor inkomend is er trouwens nog geen record van 202203% dus het zit toch in beide het probleem.
Gewijzigd op 04/03/2022 22:36:14 door Christian Snijders
- direct $_POST variabelen in je SQL is echt vragen om problemen.
- de maanden kun je met een eenvoudig sommetje berekenen als je het kwartaal weet.
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
function maandenVanKwartaal($kwartaal)
{
$eersteMaandVanHetKwartaal = $kwartaal * 3 - 2;
return [$eersteMaandVanHetKwartaal++, $eersteMaandVanHetKwartaal++, $eersteMaandVanHetKwartaal];
}
?>
function maandenVanKwartaal($kwartaal)
{
$eersteMaandVanHetKwartaal = $kwartaal * 3 - 2;
return [$eersteMaandVanHetKwartaal++, $eersteMaandVanHetKwartaal++, $eersteMaandVanHetKwartaal];
}
?>
- .$maand3."%'" Dit is om overeenkomsten in tekst te zoeken in combinatie met de LIKE operator.
Bij datums werk je gewoon met < (kleiner dan) of > (groter dan).
Of je gebruikt BETWEEN maar dat is als het ware "tot en met" dus dan moet je iets hebben als
wat dan weer omslachtig is omdat je moet gaan achterhalen wat de laatste dag van de maand is (30 of 31 ?)
Om die datum teksten te maken zou je bijvoorbeeld een datetime object kunnen gebruiken:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
// maak een nieuw DateTime object met de datum op 1 april 2022
$start = new DateTime('2022-04-01');
// maak nog een DateTime object welke afgeleid is van $start met daar opgeteld een Periode van 3 Maanden (P3M)
$end = $start->add(new DateInterval('P3M'));
$where = " WHERE `date` >= '" . $start->format('Y-m-d') . "' AND `date` < '" . $end->format('Y-m-d') . "'";
?>
// maak een nieuw DateTime object met de datum op 1 april 2022
$start = new DateTime('2022-04-01');
// maak nog een DateTime object welke afgeleid is van $start met daar opgeteld een Periode van 3 Maanden (P3M)
$end = $start->add(new DateInterval('P3M'));
$where = " WHERE `date` >= '" . $start->format('Y-m-d') . "' AND `date` < '" . $end->format('Y-m-d') . "'";
?>
- date is een gereserveerd woord in MySql. Er wordt aangeraden een andere benaming te kiezen. Dan hoef je ook geen backticks te gebruiken.
Ik ga er van uit dat je `date` kolom van het type DATE is?
Gewijzigd op 04/03/2022 23:21:47 door Frank Nietbelangrijk
Frank Nietbelangrijk op 04/03/2022 23:10:31:
Je script deugt van geen kant als ik het mag zeggen.
- direct $_POST variabelen in je SQL is echt vragen om problemen.
- de maanden kun je met een eenvoudig sommetje berekenen als je het kwartaal weet.
- .$maand3."%'" Dit is om overeenkomsten in tekst te zoeken in combinatie met de LIKE operator.
Bij datums werk je gewoon met < (kleiner dan) of > (groter dan).
Om die datum teksten te maken zou je bijvoorbeeld een datetime object kunnen gebruiken:
- date is een gereserveerd woord in MySql. Er wordt aangeraden een andere benaming te kiezen. Dan hoef je ook geen backticks te gebruiken.
- direct $_POST variabelen in je SQL is echt vragen om problemen.
- de maanden kun je met een eenvoudig sommetje berekenen als je het kwartaal weet.
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
function maandenVanKwartaal($kwartaal)
{
$eersteMaandVanHetKwartaal = $kwartaal * 3 - 2;
return [$eersteMaandVanHetKwartaal++, $eersteMaandVanHetKwartaal++, $eersteMaandVanHetKwartaal];
}
?>
function maandenVanKwartaal($kwartaal)
{
$eersteMaandVanHetKwartaal = $kwartaal * 3 - 2;
return [$eersteMaandVanHetKwartaal++, $eersteMaandVanHetKwartaal++, $eersteMaandVanHetKwartaal];
}
?>
- .$maand3."%'" Dit is om overeenkomsten in tekst te zoeken in combinatie met de LIKE operator.
Bij datums werk je gewoon met < (kleiner dan) of > (groter dan).
Om die datum teksten te maken zou je bijvoorbeeld een datetime object kunnen gebruiken:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
// maak een nieuw DateTime object met de datum op 1 april 2022
$start = new DateTime('2022-04-01');
// maak nog een DateTime object welke afgeleid is van $start met daar opgeteld een Periode van 3 Maanden (P3M)
$end = $start->add(new DateInterval('P3M'));
$where = " WHERE `date` >= '" . $start->format('Y-m-d') . "' AND `date` < '" . $end->format('Y-m-d') . "'";
?>
// maak een nieuw DateTime object met de datum op 1 april 2022
$start = new DateTime('2022-04-01');
// maak nog een DateTime object welke afgeleid is van $start met daar opgeteld een Periode van 3 Maanden (P3M)
$end = $start->add(new DateInterval('P3M'));
$where = " WHERE `date` >= '" . $start->format('Y-m-d') . "' AND `date` < '" . $end->format('Y-m-d') . "'";
?>
- date is een gereserveerd woord in MySql. Er wordt aangeraden een andere benaming te kiezen. Dan hoef je ook geen backticks te gebruiken.
Ongetwijfeld is mijn code niet de mooiste, dat "date" heb ik al jaren geleden toegepast en is met de hoeveelheid records eigenlijk ook niet meer aan te passen anders had ik dat allang gedaan.
Daarnaast die "wildcard" (%) zo noem ik 'm maar even is omdat die "date" string langer is dan alleen Ymd, die bestaat dus uit YmdHis zoals het nu is is het: 20220304231911.
Ik deed dat er dus inzetten om te zorgen dat hij het laatste stukje hoe dan ook mee pakt, of is daar een manier voor om die alsnog op een andere wijze te omzeilen?
Ik wilde namelijk de database zo klein mogelijk maken jaren geleden waardoor ik dus de datum en tijd in één veld samenvoegde en later weer splitste.
Waarom gebruik je dan niet gewoon het type DATETIME ?
Frank Nietbelangrijk op 04/03/2022 23:24:26:
Waarom gebruik je dan niet gewoon het type DATETIME ?
Toen ik dat jaren geleden toepaste had ik geen flauw benul wat ik deed "want het werkte".
toen mijn hostingprovider besloot mysql_query uit te sluiten en mysqli_query te verplichten kwam ik er ook achter dat veel dingen anders hadden gemoeten.
Ik heb alles (de query's) mezelf moeten aanleren, is niet altijd vlekkeloos gegaan.
Ben gewoon bang als ik nu kolom `date` omzet van VARCHAR(99) naar DATETIME dat het niet goed gaat komen en ik informatie zal verliezen.
maar als ik het dus goed begrijp snapt mysql "door mijn gebrabbel" in de code niet wat ik bedoel en stopt hij met tellen aan het begin van de "laatste kwartaalmaand" hij krijgt tenslotte als ik het goed begrijp de opdracht alles beneden "202203" mee te pakken in plaats van wat ik bedoelde.
Moet ik de query dan niet vertellen dat alles beneden de eerste maand van het volgende kwartaal mee moet pakken of denk ik dan te simpel?
Je kunt het prima wijzigen alleen ga je natuurlijk eerst een kopie maken van je database op een test-server en daar maak je een migratie script welke je vervolgens uitvoerig gaat testen zodat wanneer je het op de productieserver draait het gewoon werkt zonder enig probleem. en natuurlijk zorg je ook dan altijd voor een backup.
Pseudocode:
Code (php)
1
2
3
2
3
ALTER TABLE x ADD COLUMN nieuw DATETIME NULL DEFAULT NULL;
UPDATE x SET nieuw = STR_TO_DATE(oud, 'YmdHis');
-- ALTER TABLE x DROP COLUMN oud; -- pas uitvoeren als de nieuwe kolom klopt
UPDATE x SET nieuw = STR_TO_DATE(oud, 'YmdHis');
-- ALTER TABLE x DROP COLUMN oud; -- pas uitvoeren als de nieuwe kolom klopt
Zie ook:
https://dev.mysql.com/doc/refman/8.0/en/alter-table.html
https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_str-to-date
Ik heb het volgende gedaan: nu geeft hij wel het resultaat wat ik vroeg.
Nu weet ik alleen niet of die % bij <= iets uithaalt of dat ik die maar gewoon weg moet halen.
Nu zal ik dus wel moeten werken aan het schoonmaken van de code zoals Frank zei met zijn "function", scheelt tenslotte ook een stuk code en dus minder belasting voor de webserver.
De VARCHAR ga ik niet meer aanpassen omdat ik dan alle codes door de website om moet bouwen aangezien het weer net anders werkt.
En betreft bescherming tegen SQL injecties, is mysql_real_escape_string() een oplossing om toe te passen? Zo ja: als ik die toepas moet ik die in de query zetten op deze manier? (value is even een voobeeld)
Zie ook:
mysqli_real_escape_string
(Ikzelf ben fan van de object-oriented versie van Mysqli.)
Gewijzigd op 05/03/2022 14:05:18 door - Ariën -
- Ariën - op 05/03/2022 14:00:59:
Ik zou ZEKER NIET de oude mysql_xxxx() functies gebruiken.
Zie ook:
mysqli_real_escape_string
(Ikzelf ben fan van de object-oriented versie van Mysqli.)
Zie ook:
mysqli_real_escape_string
(Ikzelf ben fan van de object-oriented versie van Mysqli.)
Daar was ik van op de hoogte ;-) aangezien ik al met mysqli werk maar had dit van internet af geplukt.
Daarnaast waarschuwt Apache al zodra ik dus mysql_query's uitvoer dat deze uit gefaseerd zullen worden.
Dus op welke manier kan ik hem dan het beste uitvoeren?
Even het "schaapvoorbeeld" erbij gehaald.
1:
Code (php)
1
2
2
$schaap = mysqli_real_escape_string('De string');
mysqli_query($link, "Select * WHERE `blaat` = '".$schaap."'");
mysqli_query($link, "Select * WHERE `blaat` = '".$schaap."'");
2:
Code (php)
1
mysqli_query($link, "Select * WHERE `blaat` = '".mysqli_real_escape_string($_POST['schaap'])."'");
Alvast bedankt voor de hulp tot nu toe :-)
Gewijzigd op 05/03/2022 14:12:26 door Christian Snijders
Maar vergeet de connectie argumente niet, check dus de manual.
Je kan ook kiezen voor prepared statements.
Christian Snijders op 05/03/2022 13:34:26:
Je zal exact dezelfde resultaten hebben gekregen met
Maar op jouw manier werkt het ook, en ik zou die ingewikkelde handleiding op de site van MySQL gewoon laten zitten.
Ad Fundum op 05/03/2022 20:04:54:
Je zal exact dezelfde resultaten hebben gekregen met
Maar op jouw manier werkt het ook, en ik zou die ingewikkelde handleiding op de site van MySQL gewoon laten zitten.
Christian Snijders op 05/03/2022 13:34:26:
Je zal exact dezelfde resultaten hebben gekregen met
Maar op jouw manier werkt het ook, en ik zou die ingewikkelde handleiding op de site van MySQL gewoon laten zitten.
Ik moest beide toevoegen omdat alles voor 202203 en de huidige maand meegepakt moesten worden, doe ik alleen like '202203%' krijg ik alleen alles van deze maand.
is effectief gelijk aan
AND (`date` <= '202203YOHO'
Waarschijnlijk is het
AND (`date` <= '202203'
wat je zocht, maar dat pakt alles dt voor maart 2022 ligt. Dus ook dec 2014.
Maar "alles voor maart 2022 of in maart 2022" is wel gelijk aan "voor april 2022."
Maar het is wel heel jammer om geen datetime te gebruiken, inclusief alle handigheden die te vinden zijn in de datetime-functies.
Want een query "alles in een augustus van elk jaar" is nog te doen met like ____08%
maar alles van een dinsdag ga je niet gequery-t krijgen.
Ivo P op 05/03/2022 21:49:36:
volledige quote even geskipt..
Het was ook inderdaad de bedoeling alles voor april op te roepen en dat samen op te tellen, wat je zegt klinkt nu ook best logisch dat hij mijn query aanzag als "202203" en niet alles wat in 202203XX komt dus is eigenlijk alles lager laten zoeken dan 202204 logischer.
De hele bedoeling van mijn query is dus onbeperkt terug de tijd in gaan tot op het moment dat ik dat van hem vraag (in dit geval eind maart) er is dus geen begin of specifieke dag vereist.