[MYSQL] Verschil tussen 2 rijen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • h3nr1
  • Registratie: Oktober 2001
  • Laatst online: 13:08
Ik heb een field kilometerstand met daarin meerdere rijen met kilometerstanden. Ik wil nu een query maken waarin ik het verschil tussen de huidige rij en de voorgaande krijg.

KMstand verschil
0 0
443 443
789 346
enz

Er komt ook nog een field "getankte liters" om dan het verbruik te kunnen berekenen.

Graag hulp hierbij. Andere sugesties om deze verbruiks webpagina te maken zijn welkom

Acties:
  • 0 Henk 'm!

  • Chris_NL
  • Registratie: November 2010
  • Laatst online: 30-07-2024

Chris_NL

Miauw

Als je PHP gebruikt kan je eerst de MySQL resultaten in een string stoppen en dan deze simpele code uitvoeren:

PHP:
1
2
3
$verschil = $after - $before;
$benzinecar = $verschil * $benzineprijs;
$dieselcar = $verschil * $dieselprijs;


Meer:
http://www.phphulp.nl/php...nigvuldigen-en-delen/184/

Acties:
  • 0 Henk 'm!

  • Wolfboy
  • Registratie: Januari 2001
  • Niet online

Wolfboy

ubi dubium ibi libertas

Je kan iets als dit doen natuurlijk:

SQL:
1
2
3
4
SELECT b.kmstand, b.kmstand - a.kmstand
FROM tabel a
JOIN b ON ...
ORDER BY a.kmstand, b.kmstand


Dit gaat er natuurlijk wel vanuit dat je iets hebt om op te joinen. Zo niet, dan is dat sowieso een fout in je datamodel imho.

Blog [Stackoverflow] [LinkedIn]


Acties:
  • 0 Henk 'm!

Verwijderd

@wolfboy: hoeft niet natuurlijk. Je kan ook dezelfde tabel nog een keer op zichzelf joinen met aliassen. Je kan het dan zo krijgen dat je steeds opvolgende km-standen van elkaar aftrekt. ik heb zelf ergens een query hangen die iets dergelijks doet (maar dan niet met km-standen ;) )

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 15:11
Je bent inderdaad op zoek naar een 'self-join', waarmee je een record joined met zijn vorige record.
Als je iets van een volgnummer hebt is dat eenvoudig met een b.volgnummer=a.volgnummer-1. Anders wordt het iets complexer en wordt een subquery misschien handiger.

Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

frickY schreef op zondag 02 januari 2011 @ 12:40:
Je bent inderdaad op zoek naar een 'self-join', waarmee je een record joined met zijn vorige record.
Als je iets van een volgnummer hebt is dat eenvoudig met een b.volgnummer=a.volgnummer-1. Anders wordt het iets complexer en wordt een subquery misschien handiger.
Ik zou hiervoor geen volgnummer gebruiken, je weet hoe het met die bonnetjes gaat. Dan kun je achteraf niets meer toevoegen zonder daar weer moeilijk mee te doen door gewenste volgnummer op te zoeken, alle nummers die hoger zijn dan dat nummer eentje op te hogen en dan je uiteindelijke insert te doen.

Ik zou gewoon een datum invoer opslaan, en dan vergelijken met het record met de vorige datum. Hier moet je met een subquery en limit wel uitkomen.

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

  • iisschots
  • Registratie: November 2002
  • Laatst online: 17-09 10:35
>>> PRG

Hackerspace in Friesland | www.frack.nl | Bezig met opzetten, help mee!


Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Ik zou gewoon 2 kolommen, from (vorige bekende KM stand) en current (huidige KM stand)

Dan kan je simpel SELECT current-from AS result FROM tabel

Self joinen kan ook maar maakt het een stuk complexer.

Acties:
  • 0 Henk 'm!

  • h3nr1
  • Registratie: Oktober 2001
  • Laatst online: 13:08
Bedankt allen voor de reakties. Ik ga ermee aan de slag en merk ook dat ik nog tekort schiet in mijn sql kennis.
(ben vrij newbie op dit gebied)

Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
ReenL schreef op zondag 02 januari 2011 @ 18:57:
Ik zou gewoon 2 kolommen, from (vorige bekende KM stand) en current (huidige KM stand)

Dan kan je simpel SELECT current-from AS result FROM tabel

Self joinen kan ook maar maakt het een stuk complexer.
Zou ik niet doen, dan denormaliseer je alle gegevens en moet je extra code schrijven om bij het schrijven van een record eerst het vorige record op te halen en die waarde te kopiëren naar het nieuwe record. Dat je dezelfde data twee keer zou moeten opslaan bij die oplossing zou al een rood licht moeten laten branden.

Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Googol is your friend, handige tut hier: http://www.sqlteam.com/article/calculating-running-totals

Is misschien niet precies wat je wil of nodig hebt, maar sowieso handig om even te kijken.

[ Voor 32% gewijzigd door Davio op 03-01-2011 13:28 ]


Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Denormaliseren is niet altijd een slecht iets.

Ik heb geen inzicht in de werking van de applicatie dus ik ga ook niet zeggen dat mijn oplossing beter is.

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
YopY schreef op maandag 03 januari 2011 @ 12:54:
[...]
Zou ik niet doen, dan denormaliseer je alle gegevens en moet je extra code schrijven om bij het schrijven van een record eerst het vorige record op te halen en die waarde te kopiëren naar het nieuwe record. Dat je dezelfde data twee keer zou moeten opslaan bij die oplossing zou al een rood licht moeten laten branden.
Ik zou er toch voor kiezen om het of te denormaliseren of het datamodel drastisch te veranderen.

Self-joins zijn op de lange duur (met tabellen die steeds meer uitdijen) vaak performancekillers 1e klas. Heb je er straks 1 miljoen records instaan dan heb je vaak een uitdaging.

Gaat het echter enkel om een persoonlijk iets waarbij je blij mag zijn als je 1000 records aanwas per jaar hebt, dan is een self-join weer het snelst gerealiseerd.

Acties:
  • 0 Henk 'm!

  • h3nr1
  • Registratie: Oktober 2001
  • Laatst online: 13:08
Wellicht ter aanvulling. Ik hoef geen extra kolom. Enige wat ik eruit wil halen is het verbruik. Ik heb dus dit

KMstand Aantal liters
444 35
788 27

En dan wil ik het verbruik per keer berekenen.

Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
En ik geef een oplossing dmv een extra kolom, omdat de performance van je applicatie straks om te huilen is doordat je een self join gebruikt.

Tuurlijk "hoeft" het niet, de oplossingen die gegeven waren voor mijn post zullen ook prima werken, zolang de tabel maar niet te groot wordt. Of het aantal selects beperkt blijft.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ben ik de enige die zich afvraagt waarom je dit in hemelsnaam per se in SQL wilt oplossen?
.edit: nee, want ik heb de eerste reactie duidelijk niet gelezen :X

[ Voor 31% gewijzigd door .oisyn op 07-01-2011 02:12 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op vrijdag 07 januari 2011 @ 02:11:
Ben ik de enige die zich afvraagt waarom je dit in hemelsnaam per se in SQL wilt oplossen?
.edit: nee, want ik heb de eerste reactie duidelijk niet gelezen :X
Eensch...
Waarom een datamodel veranderen wanneer het in de code veel netter kan. Lijkt mij een beetje raar. Ook wil hij sowieso een overzichtpagina, dus code ga je toch wel gebruiken.

Acties:
  • 0 Henk 'm!

  • h3nr1
  • Registratie: Oktober 2001
  • Laatst online: 13:08
Voorlopig heb ik het kunnen oplossen met onderstaand php. Vast niet heel netjes maar het werkt. En het zijn mijn eerste stappen in het php.

Opbouwende kritiek sta ik voor open.

$x=1;
$y=0;
while($row = mysql_fetch_array($result))
{
$kmstand[$x]=$row['KMstand'];
$gemkm=$kmstand[$x]-$kmstand[$y];
$gemverb=$gemkm/$row['Liters'];
echo "<tr>";
echo "<td>" . $x . "</td>";
echo "<td>" . $kmstand[$x] . "</td>";
echo "<td>" . $row['Liters'] . "</td>";
echo "<td>" . $gemkm . "</td>";
echo "<td>" . round($gemverb,2) . "</td>";
echo "</tr>";
$x++;
$y++;
}

Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Is niet echt optimaal, je hebt namelijk helemaal geen array nodig, alleen de huidige waarde en de vorige waarde.

Als je je code tussen [cod3=PHP][/cod3] tags zet, krijg je nette formatting. (waarbij 3 = e obv).

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$oldKm = 0;
$i = 0;

while($row = mysql_fetch_assoc($result))
{
    $i++;
    $km = $row['KMstand'];
    $deltaKm = $km - $oldKm;
    $verbruik = $deltaKm/$row['Liters'];

    echo '
    <tr><td>'.$i.'</td><td>'.$km.'</td><td>'.$row['Liters'].'</td><td>'.$deltaKm.'</td><td>'.round($verbruik,2).'</td></tr>';

    $oldKm = $km;
}

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Maar je zult sowieso iets van een tijd of volgnummer op moeten nemen, anders is het nooit gegarandeerd dat je de juiste volgorde uit je tabel krijgt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • h3nr1
  • Registratie: Oktober 2001
  • Laatst online: 13:08
.oisyn schreef op zaterdag 08 januari 2011 @ 00:02:
Maar je zult sowieso iets van een tijd of volgnummer op moeten nemen, anders is het nooit gegarandeerd dat je de juiste volgorde uit je tabel krijgt.
Ik heb in mijn form nu ook een date field. Zodat je na het tanken een kmstand, aantal liters, bedrag en en datum moet invullen. De datum word automatisch ingevuld.

Acties:
  • 0 Henk 'm!

  • h3nr1
  • Registratie: Oktober 2001
  • Laatst online: 13:08
Davio schreef op vrijdag 07 januari 2011 @ 22:55:
Is niet echt optimaal, je hebt namelijk helemaal geen array nodig, alleen de huidige waarde en de vorige waarde.

Als je je code tussen [cod3=PHP][/cod3] tags zet, krijg je nette formatting. (waarbij 3 = e obv).
Bedankt, ik heb je code overgenomen en aangevuld/aangepast en werkt prima. Zal later nog uitzoeken hoe dat zit met array en assoc. Kom ik vast wel uit met googol.
Snap alleen dat [cod3=PHP][/cod3] tags niet goed.

Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Nou, die code-tags zijn voor hier op Tweakers.
Klik maar op UBB-codes als je een bericht plaatst...

Die date-field heb je helemaal niet nodig op je form als die toch automatisch gevuld wordt.
Dan kun je hem beter meegeven in je INSERT-statement.
$sql = "INSERT INTO table SET datum = NOW()".
NOW() is een (My)SQL-functie die de huidige datum en tijd geeft.

Verschil tussen mysql_fetch_array en mysql_fetch_assoc is dat je bij de eerste standaard een array krijgt waarvan je de waarden zowel met normale integer indices (van 0 t/m de lengte van de array - 1) als kolomnamen op kunt vragen.
Bij mysql_fetch_assoc krijg je een array met alleen de kolomnamen als indices.

Ik gebruik zelf vrijwel altijd alleen de 2e variant, omdat kolomnamen duidelijk zijn en je code dan niet breekt als je in je database de volgorde van de velden aanpast. Je code breekt dan wel weer als je de naam van een veld aanpast, maar dat kun je voorkomen door in je select-query iets te doen als
SELECT kolom AS alias FROM tabel. En dan $row['alias'] gebruiken.
Je kan die AS ook weglaten, dan is de betekenis hetzelfde, maar de leesbaarheid minder.

Acties:
  • 0 Henk 'm!

  • h3nr1
  • Registratie: Oktober 2001
  • Laatst online: 13:08
Davio, bedankt. Heldere uitleg en ik kan in het vervolg weer wat mooiere posts maken ;)

De date field laat ik even zo. Nu kan ik makkelijk achteraf een bonnetje invoeren.

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Davio schreef op zaterdag 08 januari 2011 @ 02:30:
Je code breekt dan wel weer als je de naam van een veld aanpast, maar dat kun je voorkomen door in je select-query iets te doen als
SELECT kolom AS alias FROM tabel. En dan $row['alias'] gebruiken.
Je kan die AS ook weglaten, dan is de betekenis hetzelfde, maar de leesbaarheid minder.
Wat is de toegevoegde waarde van die alias hier?

Zo goed als altijd wil ik dat al mijn query's breken als ik de naam van een veld aanpas, als ik dat niet zou willen maak ik wel een view aan met constante veldnamen.

Lijkt me niets irritanter/bugaantrekkend als in de dbase de ene veldnamen te hebben en dan in code het opeens ergens totaal anders over te hebben.

Zoals ik al zeg, als ik een veld voornaam verander naar achternaam wil ik dat overal mijn query's/code breekt zodat ik alles langs moet gaan en fixen. Anders kom ik geheid later in de problemen als ik een voornaam in code heb, terwijl ik in de dbase dit hele veld niet heb.

Aliassen vind ik schitterend voor tabellen in query's, voor functies over velden ( min/max/count/upper/lower/etc ) maar in principe wil ik gewoon dat "elk" veld in mijn resultset overeen komt met een dbase veld.
Pagina: 1