Avatar billede johny Nybegynder
20. februar 2008 - 17:48 Der er 6 kommentarer og
1 løsning

Data fra db og funktioner

Ja, jeg vidste ikke lige helt hvad jeg skal skrive som titel, for det er nok en større omgang. Det jeg gerne vil, er nemlig at hive nogle specifikke data ud af en database med så få kald til databasen som muligt. Først lige lidt om db'en:

Det er en database der er struktureret til at deltagere på en festival, hvor de bor, hvad de hedder, hvor længe de skal være der osv. og i den forbindelse er der kommet en del forskellige tabeller:
1) En tabel over pladserne og om de er frie eller ej.
2) En tabel med oplysninger til den reserverede plads, og hvilken type enhed der er tale om (med eller uden fortelt f.eks.).
3) En tabel over "beboere" på pladsen.
4) En tabel med overnatninger (mellemled i et mange til mange forhold)
5) En tabel med priser
*) Diverse andre der ikke lige er relevante her.

Det jeg så har når jeg går ned i systemet, er den "sessionid" som der ligger i reservations tabellen (tabel 2), og det jeg skal have ud, er følgende:

a) Pladsens navn:
Denne kan jeg få fra tabel 1, vha. en fk (foreign key) i tabel 2.
b) Enheds typen:
Denne kan jeg få fra tabel 2 vha. min sessionid.
c) Antal overnattende:
Dem kan jeg finde i tabel 3 vha. min sessionid, da den er fk i tabel 3.
d) Antal overnatninger:
Dem kan jeg finde i tabel 4 vha. en id fra dem jeg skal have fundet i c).
e) Priser:
Så skal jeg have hentet alt der står i pris tabellen (tabel 5), selvom det er nok hvis jeg kun får den ene kolonne her fra (der er 2 kolonner med 4 rækker).

Det jeg så havde håbet lidt på, var at jeg kunne klare det i aller højst 3 kald, og meget gerne mindre. c) og d) kan jo klares vha. Count(), men jeg ved så ikke om det kan lade sig gøre hvis det skal flettes sammen med alt muligt andet? Og a), b) og e) forestillede jeg mig kunne klares vha. noget inner join, men kan det også lade sig gøre når nu tabel 5 ikke har noget den deler med tabel 1 og 2?

Det helt idéelle ville jo være at kunne trække det ud som én tabel med 8 kolonner og 1 række, men kan det lade sig gøre? Det vil jo kræve en mærkelig blanding af count() metoder, plus at vende tabel 5, så jeg får mine rækker ud som kolonner?

Jeg håber jeg har kunnet gøre det nogenlunde klart hvad jeg ville? På forhånd tak!
Avatar billede recli Nybegynder
22. februar 2008 - 08:56 #1
Jeg tror, at du bliver nødt til at forklare det lidt nærmere. Jeg har kigget på din beskrivelse i flere runder, men ikke rigtigt kunnet finde ud af, hvordan du har data liggende - og hvad du egentlig vil have trukket ud, når nu du snakker om både COUNT og om at vende tabel 5's rækker til kolonner.

  /Lars
Avatar billede johny Nybegynder
22. februar 2008 - 09:56 #2
Det forstår jeg godt. Er også en anelse forvirrende. Jeg prøver lige at specificere det lidt nærmere.. :)

table 1) indeholder oplysninger om pladserne, i form af pladsnavn og om den er optaget.

table 2) indeholder så de oplysninger der er på pladsen når den er optaget. Det er bl.a. et session's id, vogntype (campingvogn m. el. u. fortelt), reg. email, og nogle andre ting.

table 3) indeholder oplysninger om de overnattende. De har hvert et unikt id, og har sig tilknyttet et session's id, og informationer om personen.

table 4) er en tabel med alle overnatningerne enkeltvis. De kan nemlig overnatte tre forskellige nætter i en hvilken som helst sammensætning. Så det denne tabel indeholder er blot et persons id (fra table 3) og et nat id, som er knyttet til en tekstuel representation i en anden tabel, men siden jeg kun er interesseret i antallet af overnatninger er den tabel ikke interessant.

table 5) er en list over alle priserne. De har en id, en pris og en tekstuel representation. Id'en ligger som fk i table 2), men de er nummeret 1-4, så jeg ved selv hvilke der er hvilke.

Det jeg så helst vil have returneret er en tabel med kun én række, nemlig følgende:
Pladsnavn; Enhedstypen; Antal overnnatende; Antal overnatninger; pris1; pris2; pris3; pris4;

På den måde trækker jeg bare værdierne ud en efter en og bruger dem til det jeg nu skal. (Skal lave en masse udregninger bl.a.)

Grunden til jeg nævnte count var, at de resultater jeg skal nå frem til er antallet af beboere på pladsen, og antallet af overnatninger, og sådan set ikke mere hvad de to ting angår (c og d). Men det betyder dog ikke at jeg har noget imod at få dem ud som liste og så tælle på dem, jeg vil bare helst belaste db'en så lidt som muligt.

Men med min ringe viden til sql ville min egen løsning være:
Hive resultat a og b ud med en inner join, så hive en liste over de overnattendes id'er ud, så kører et kald til db'en for hver overnattende, for at lave en count på de overnatninger de har, og endelig til sidst ville jeg så hive priserne ud.

Jeg synes bare det er lige lovlig mange kald, især hvis der er 4+ overnattende på en plads, og så ville jeg høre om der ikke var en "smartere" løsning.

Håber det gjorde det lidt mere klart?
Avatar billede recli Nybegynder
22. februar 2008 - 10:37 #3
Ok, nu tror jeg, jeg forstår, hvad du gerne vil :-)

I forbindelse et tidligere spørgsmål om udtræk af data viste jeg i et lille eksempel, hvordan man kan bruge MySQLs funktioner IF og SUM til at få 'vendt' data, der ligger i rækker til sammentalte data i en eller flere kolonner. Umiddelbart ser det ud til at være samme princip, du skal bruge - blot kombineret med en længere JOIN-operation...

Men her er eksemplet til inspiration:

SELECT  spm AS Spørgmål,
  SUM(IF(bruger_svar='ja',1,0)) AS "Ja",
  SUM(IF(bruger_svar='Nej',1,0)) AS "Nej"
  FROM svar
  GROUP BY spm
  ORDER BY spm;

Den tæller separate rækker med svar sammen og viser dem på følgende måde:

+----------+------+------+
| Spørgmål | Ja  | Nej  |
+----------+------+------+
|        1 |    2 |    1 |
|        2 |    2 |    1 |
|        3 |    2 |    1 |
+----------+------+------+

God fornøjelse...
  /Lars
Avatar billede johny Nybegynder
22. februar 2008 - 15:16 #4
Hej igen, tak for svaret, det var et rigtig god feature der, men er bange for at den ikke gør det jeg skal bruge.

F.eks. kan jeg sagtens merge resultat a og b og få dem retur, men hvordan får jeg e som du gav et løsningsforslag til der, med ind på den? Altså, hvordan kan jeg joine Tabel 1, 2 og 5 "korrekt"? Der er jo ikke noget rigtig bindeled.

Tabel 3 og 4 fik jeg endelig klaret i 1 kald. Er bare mig der er lidt grøn i faget med SQL kald.. ^^

Igen, kunne det lade sig gøre at blande 1, 2 og 5? For ellers nytter det jo ikke meget at jeg kan vende tabellen, for så kunne jeg lige så godt hive det ud som rækker..
Avatar billede johny Nybegynder
22. februar 2008 - 15:32 #5
Ahh, nu fandt jeg så ud af det. Det jeg skulle, var bare at lave select statements i mine select statements, og glemme alt om inner join. Så virkede det. :) Blev lidt af en killer:

SELECT stays.id, night FROM stays INNER JOIN participants ON stays.id = participants.id WHERE session = $SESSION
SELECT row, num, type, (SELECT value FROM price WHERE price=1) AS price1, (SELECT value FROM price WHERE price=2) AS price2, (SELECT value FROM price WHERE price=3) AS price3, (SELECT value FROM price WHERE price=4) AS price4 FROM free_spots INNER JOIN spots ON free_spots.spotid = spots.spotid WHERE session = $SESSION AND spots.voided=0

Men mange tak for hjælpen! Bare smid et svar, og pointene er dine.. :)
Avatar billede johny Nybegynder
22. februar 2008 - 15:33 #6
Ahh, det blev lige lidt forvirrende, linje 1 i min kommando, var løsningen på c,d og resten (linje 2-5) var løsningen på a,b og e.
Avatar billede recli Nybegynder
22. februar 2008 - 16:20 #7
Ja, det blev lidt af SQL-forespørgsel, du fik strikket sammen der.

  /Lars
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester