Mijn database is opgemaakt met de volgende velden,
Id, speler en dan w1 tot en met w26.
Nu wil ik graag tellen hoever keer bvb de waarde 2 voorkomt in de velden w1 tot en met w26 maar niet bvb het veld id want daar komt ook een 2 in voor. Mogelijke waarden in die velden zijn, leeg. 0, 1 ,2 of X.
Ik probeerde met mysql num rows maar het is logisch dat dit niet werkt. Met mysql num fields bind ik het niet.
Ik wil dus weten hoever keer een 2 voorkomt bij bvb speler Marc die id 3 heeft.
Misschien kan de topicstarter eerst uitleggen wat die w1 t/m w26 precies betekenen, en waarom (inderdaad) deze waarden niet in een aparte tabel opgeslagen zijn. Dat laatste zou dit vraagstuk namelijk een stuk eenvoudiger (zo niet triviaal) maken.
De velden w1 tem w26 zijn de speelweken. 0 staat voor verlies, 1 staat voor gelijkspel en 2 voor winst. X staat voor vrij deze week. De reden dat het zo is opgemaakt is omdat ik een beginner ben en dit klassementje opmaken in php, wat prima lukt, een hobby is. Nu wil ik per speler grafiekjes tekenen en zo maar daarvoor heb ik percentages nodig. Die grafiekjes teken ik met phpgraphlib, maar dit even ter zijde.
Ohja, sorry voor de schrijf fouten maar ik stuur via smartphone en heb geen brilletje ter beschikking waar ik ben :-)
Ben en Thomas hebben natuurlijk gelijk over het normaliseren, maar mocht dat nou een probleem zijn dan kan het zo (niet heel fraai dus)
SELECT id, speler,
CASE WHEN w1 = '2' THEN 1 ELSE 0 END +
CASE WHEN w2 = '2' THEN 1 ELSE 0 END +
.. herhaal voor alle w's tot/met
CASE WHEN w26 = '2' THEN 1 ELSE 0 END AS aantalkeer2
FROM jouwtabel
Met de CASE vervang je elke Wx = '2' door 1 en die tel je op.
Natuurlijk hebben die mensen gelijk, netjes is het niet.
Ik zal eens aan de slag gaan met uw oplossing. Je hoort wel als het gelukt is.
Alvast bedankt.
?
Onbekende gebruiker
07-10-2015 13:21
gewijzigd op 07-10-2015 13:23
Vervang in onderstaande query de tabelnaam met de daadwerkelijke naam van je tabel, en het getal 2 met het getal waarin je in alle kolommen wilt zoeken, en `id` = 3 is natuurlijk voor de account van de speler.
SELECT
SUM(n) AS `totaal`
FROM
( SELECT COUNT(*) AS `n` FROM `tabelnaam` WHERE `id` = 3 AND `w1` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w2` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w3` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w4` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w5` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w6` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w7` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w8` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w9` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w10` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w11` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w12` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w13` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w14` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w15` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w16` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w17` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w18` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w19` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w20` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w21` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w22` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w23` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w24` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w25` = 2
UNION SELECT COUNT(*) FROM `tabelnaam` WHERE `id` = 3 AND `w26` = 2
) AS `temp`
Toevoeging op 07/10/2015 13:35:20:
De anderen bedoelen met normaliseren is dat je hetzelfde soort gegeven niet over meerdere kolommen verdeelt, maar over meerdere tabellen. Dan kun je een verdeling krijgen als:
TABEL speler:
+ KOLOM id
+ KOLOM naam
TABEL antwoord:
+ KOLOM id
+ KOLOM volgnummer
+ KOLOM waarde
+ KOLOM tekst
Nadeel is wel dat je dan eerst een query moet schrijven om alles te kunnen zien, in plaats van op de tabelnaam te klikken. Dat wordt dan iets als
SELECT speler.naam, speler_antwoord.tekst
FROM speler_antwoord
LEFT JOIN speler ON (speler.id = speler_antwoord.speler_id)
LEFT JOIN antwoord ON (antwoord.id = speler_antwoord.antwoord_id)
ORDER BY speler.naam, antwoord.volgnummer
Een ander nadeel in deze constructie is dat het ietsje ingewikkelder wordt om ervoor te zorgen dat een enkele speler niet meerdere dezelfde antwoorden geeft. En als je mogelijk wilt maken dat een speler vaker een rijtje antwoorden mag geven, dan moet je met nog een tabel werken als:
TABEL toets
+ KOLOM id
+ KOLOM datum
en dan de tabel speler_antwoord uitbreiden met een kolom toets_id. En ja, je kunt dan ook de kolom speler_id verplaatsen naar de tabel toets, het is maar net wat handig is.
Toevoeging op 07/10/2015 13:38:27:
Als je dat allemaal hebt gedaan wordt een query op je data eenvoudiger, je kunt dan volstaan met:
SELECT
SUM(antwoord.waarde) AS `Totaal`
FROM
speler_antwoord
LEFT JOIN antwoord ON (antwoord.id = speler_antwoord.antwoord_id)
WHERE
speler_id = 3;
Als je meerdere queries maakt helpt het om een VIEW te maken op de tabel speler_antwoord waarin de JOINs verwerkt zijn.
Je kunt natuurlijk bovenstaande beest van een query overnemen en dan blij constateren dat het werkt, maar je maakt je probleem alleen maar groter.
Stap zo snel mogelijk over op een genormaliseerd model, want hoe langer je wacht, hoe meer code er gebaseerd gaat zijn op het foute model.
Ik vraag me om te beginnen af, waarom er 26 speelweken zijn. Een jaar bevat 52, of 53!, weken.
Dus kans is aanwezig dat er meer dan 26 gaan komen? Dan zul je naast je tabel ook alle query's moeten aanpassen.
En wat als we een tweede jaar ingaan? Wordt dan de data van het vorige jaar gewist?
Zou je een tabel hebben met de kolommen "speelronde" en "seizoen", dan kan in seizoen eenvoudig een 2e, 3e en 10e jaar opslagen worden, en raak je geen oude data kwijt.
Ja, het is even wat moeite, maar je komt alleen maar verder in de knoop als je het uitstelt.
Er zijn maar 7 spelers. Er wordt exact 26 keer gespeeld. Alles draait lokaal, het is dus puur voor eigen gebruik. Natuurlijk hebben jullie gelijk, ik moest een tabel spelers gemaakt hebben en een tabel uitslagen, dit ging het alles makkelijker maken, maar het wordt dus niet uitgebreid, vandaar. Iedereen bedankt om te reageren en van zodra er tijd is ga ik aan de slag.
Groetjes
?
Onbekende gebruiker
08-10-2015 09:11
gewijzigd op 08-10-2015 09:12
<...> hoe langer je wacht, hoe meer code er gebaseerd gaat zijn op het foute model.
In het algemeen is normalisatie nuttig, anders hadden we daarvoor geen databases. Maar denormalisatie is niet per sé fout. Je kunt er bewust voor kiezen om performancewinst te halen, als het toepassen van een of meerdere JOINs zwaar weegt op de beschikbare resources.
Je kunt JOINs sneller maken door gebruik van indices. Omdat indices ook moeten worden geadministreerd door de database zijn ze pas effectief wanneer de grootte van de opgevraagde subset kleiner is dan ruwweg 15% van de totale dataset.