Räkna kolumner med visst värde i SQL

Permalänk

Räkna kolumner med visst värde i SQL

Vi antar att jag har t.ex. denna tabell:

NAMN ÄRTSOPPA KÖTTBULLAR POTATIS FISKPINNAR ... Pelle x x Lisa x Olle x x x . . .

Nu vill jag veta följande:

1) Hur många olika rätter tycker varje person om? (Alltså räkna antalet "x" i varje rad.)

2) Hur många personer tycker om en rätt, två rätter, tre rätter, osv?

Kan nån vänlig typ hjälpa mig att lösa detta med SQL? (Gärna MySQL.) C/C++ kombinerat med SQL är också ett alternativ om det behövs.

Nej, det är inte en skoluppgift. (Gick ut universitetet för tre år sedan... )

Permalänk
Medlem

Om du i stället för att lagra X, då en person tycker om en maträtt, lagrar siffran 1 (lagra siffran 0 om de inte giller en viss maträtt) så kan du skriva en SQL-sats liknande:

SELECT namn, (ärtsoppa + köttbullar + potatis + fiskpinnar + alla_andra_kolumner_med_maträtter) AS Antal FROM dintabell

Lägger du till maträtter måste du dock in i och ändra i SQL-satsen vilket inte är speciellt smidigt eller smart. Jag skulle hellre satsa på att ändra desigenn av tabellern enligt t.ex:

PERSONER +------------------+ | personID | namn | +------------------+ | 1 | Pelle | | 2 | Lisa | | 3 | Olle | +------------------+ MATRÄTTER +-------------------------+ | maträttsID | maträtt | +-------------------------+ | 1 | Ärtsoppa | | 2 | Köttbullar | | 3 | Potatis | | 4 | Fiskpinnar | +-------------------------+ TYCKER_OM +-----------------------+ | personID | maträttsID | +-----------------------+ | 1 | 1 | | 1 | 2 | | 2 | 3 | | 3 | 2 | | 3 | 3 | | 3 | 4 | +-----------------------+

Följande SQL-sats borde då visa antal maträtter någon tycker om:

SELECT namn, COUNT(maträttsID) AS Antal FROM personer, tycker_om WHERE personer.personID = tycker_om.personID GROUP BY personer.personID, namn

Din andra fråga blir lite klurigare, men borde kunna lösas med vyer. Skapa en vy som listar antalet maträtter som varje person tycker om:

CREATE VIEW antal_maträtter AS SELECT COUNT(maträttsID) AS antal FROM tycker_om GROUP BY personID

Därefter borde följande funka:

SELECT antal AS Antal_maträtter, COUNT(*) AS Antal_personer FROM antal_maträtter GROUP BY Antal

Permalänk
Medlem

fråga två besvaras ju av funktionen som i php heter mysql_affected_rows() (efter den första queryn) som säkerligen borde finnas med i alla vettiga sqlbibliotek till c++ också?!

Permalänk

Tack ska ni har för svaren!

Citat:

Ursprungligen inskrivet av Rimion

[Lång lösning]

Ska ta och kolla lite närmare på din lösning. Saken är den att tabellen ja ska använda (motsvarande den i mitt exempel men något större) finns redan. Den har några tusen namn och "maträtterna" (i verkligheten något annat) är närmare 30 st. Dessutom innehåller den annan information.

Ditt förslag till ändring av design hade säkert varit bra just här, men tabellen tjänar även andra syften, för vilka min lösning lämpar sig bättre.

Citat:

Ursprungligen inskrivet av totoo
fråga två besvaras ju av funktionen som i php heter mysql_affected_rows() (efter den första queryn) som säkerligen borde finnas med i alla vettiga sqlbibliotek till c++ också?!

Jag använder nån äldre version av MySQL++ (som är kompatibel med Microsoft Visual C++ 6.0). Får kolla om det finns nåt liknande där.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Pink Lemonade

Den har några tusen namn och "maträtterna" (i verkligheten något annat) är närmare 30 st. Dessutom innehåller den annan information.

Ditt förslag till ändring av design hade säkert varit bra just här, men tabellen tjänar även andra syften, för vilka min lösning lämpar sig bättre.

Törs nästan lova att du kan göra precis allt som du gör nu minst lika smidigt enligt Rimions förslag. Du använder en relationsdatabas men anser dig kunna hantera relationerna bättre själv (du håller reda på vad som är maträtter istället för databasen) än vad databasen kan. Förvänta dig ingen bra prestanda. Men har man byggt fast sig i en dålig design så får man ju bita i det sura äpplet....

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av totoo
fråga två besvaras ju av funktionen som i php heter mysql_affected_rows() (efter den första queryn) som säkerligen borde finnas med i alla vettiga sqlbibliotek till c++ också?!

Nope.

Citat:

Get the number of affected rows by the last INSERT, UPDATE or DELETE query ...

Citat:

Ursprungligen inskrivet av Edmund
Förvänta dig ingen bra prestanda. Men har man byggt fast sig i en dålig design så får man ju bita i det sura äpplet....

Även om jag håller med dig rent generellt, så är det allt för ofta så att det inte är en själv som bygger fast sig i en dålig design. Snarare är det så att man får i uppgift att fixa problem med en befintlig design och då är det ofta alldeles för mycket jobb att göra grundläggande förändringar.

Permalänk

Jag går på Edmunds linje. Tror du kommer att tjäna mycket på att göra om databasen. Det är just därför man har relationsdatabaser. Jag har svårt att tänka mig att det är bättre med denna design i andra syften, särskilt som man kan bygga upp index etc. för att göra den bättre.

Visa signatur

/Mvh Stefan

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Kennel
Nope.

Vadå, är inte bara det där nån detalj som de har glömt att uppdatera i manualen?

Det fungerar ju som det ska att räkna träffar i en select också med den funktionen i alla fall.

Permalänk
Testpilot

Funkar inte det här för att räkna antal maträtter som folk tycker om?

$resultat = mysql_query("SELECT * FROM `tabell` WHERE `korv`='x' OR `fiskpinnar`='x' OR `potatis`='x'"); while($person = mysql_fetch_assoc($resultat)){ echo $person['namn'].' gillar '.(count($person)-1).'st maträtter.<br />'; }

Exemplet förutsätter då att du bara ha en kolumn som inte är en maträtt, byt bara ut ettan mot antal kolumner som inte är maträtter.

Eller är jag helt ute och cyklar?

Visa signatur

Kolla gärna in min RGB-LED-ljusstake i galleriet
[Gigabyte GA-Z97MX-Gaming 5][Intel Core i5 4690K][Corsair XMS3 16GB][Asus GeForce RTX 2060 Super Dual Evo OC]

Permalänk
Medlem

ful ifsats med ca 30 alternativ bara... Men visst borde detta fungera.

edit: Eller det där blir inte alls rätt... Du har ju select *, därför spelar det ju ingen roll om personen gillar en maträtt eller alla, alla fält hämtas ju till arrayen ändå...

Men kan du lägga till lite kod för att lösa det? I så fall kan man ju göra såhär... Eller vänta.. Nu ska jag improvisera lite....

1:

select name, CONCAT(ÄRTSOPPA, ÄRTSOPPA, POTATIS, FISKPINNAR) as foodResult from tabellen

Låt säga att fältet har ett X eller är tomt, då kan detta fungera.
Alla dina x kommer att läggas på rad i en lång sträng som vi kommer att kalla för foodResult.

Sedan tar du en strlen på foodResult och får reda på hur många X du har, där har du svaret på hur många måltider personen gillar.

2:

För att få fram ett svar här så itererar du igenom alla svar som hamnar i din resultatarray från mysql och de som längden tre på foodResult gillar ju tre rätter....

Om du vill sortera enligt regeln hur många maträtter de äter så kan du säkert i queryn lägga till order by foodResult på slutet.

Permalänk
Testpilot

Aha, missade att det rörde sig om så pass många maträtter, trodde det var typ 5st
Då är ju relationstabeller mycket bättre.

Visa signatur

Kolla gärna in min RGB-LED-ljusstake i galleriet
[Gigabyte GA-Z97MX-Gaming 5][Intel Core i5 4690K][Corsair XMS3 16GB][Asus GeForce RTX 2060 Super Dual Evo OC]

Permalänk
Citat:

Ursprungligen inskrivet av Edmund

Törs nästan lova att du kan göra precis allt som du gör nu minst lika smidigt enligt Rimions förslag. Du använder en relationsdatabas men anser dig kunna hantera relationerna bättre själv (du håller reda på vad som är maträtter istället för databasen) än vad databasen kan. Förvänta dig ingen bra prestanda. Men har man byggt fast sig i en dålig design så får man ju bita i det sura äpplet....

Citat:

Ursprungligen inskrivet av Guru Meditation
Jag går på Edmunds linje. Tror du kommer att tjäna mycket på att göra om databasen. Det är just därför man har relationsdatabaser. Jag har svårt att tänka mig att det är bättre med denna design i andra syften, särskilt som man kan bygga upp index etc. för att göra den bättre.

Grejen är den, att tabellen bygger på ett Excel-dokument som jag sparat som csv och importerat i MySQL. Att designa om databasen och överföra all information vore mera arbetsdrygt än att t.ex. lösa mina problem med "våld" i MySQL++. Det blir nog lättast att byta x:en mot ettor istället.

Men tack för att ni kom med konstruktiva förslag!

Permalänk
Medlem

det är helt klart en bra lösning, men om du inte vill byta ut alla X så fungerar min lösning ungefär likadant också, och där är tecknet oväsentligt, förutsatt att det är samma tecken i alla. Dock är den kanske inte fullt så snabb då den får jobba med strängar istället för att bara addera tal, men det är detaljer.

Permalänk

Jo, de har du rätt i. Snabbheten är inte heller väsentlig här eftersom jag bara kommer att tillämpa detta högst ett par gånger.

Tack igen.

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av totoo
Vadå, är inte bara det där nån detalj som de har glömt att uppdatera i manualen?

Det fungerar ju som det ska att räkna träffar i en select också med den funktionen i alla fall.

Om jag läser manualen rätt så fungerar det så för mysqli, men inte för den gamla providern. Att det fungerar i den nya versionen var nog pga att för många använde det på fel sätt. Om du kör en query i mysql (.exe) så ser du att den inte rapporterar hur många rader som blev påverkade, bara antalet rader som returnerades. Antagligen mappar PHP om detta så att den kör num_rows på resultaten om den upptäcker att man försöker köra affected_rows efter en SELECT.

Permalänk
Citat:

Ursprungligen inskrivet av Pink Lemonade
Grejen är den, att tabellen bygger på ett Excel-dokument som jag sparat som csv och importerat i MySQL. Att designa om databasen och överföra all information vore mera arbetsdrygt än att t.ex. lösa mina problem med "våld" i MySQL++. Det blir nog lättast att byta x:en mot ettor istället.

Men tack för att ni kom med konstruktiva förslag!

Spara de olika kolumnerna i olika csv-filer och importera till olika tabeller så är saken biff?

Visa signatur

/Mvh Stefan

Permalänk

Jag löste det genom att använda CONCAT ock räkna längden på strängarna i C++ som totoo föreslog.

Tack än en gång till alla som försökt hjälpa!