Avatar billede kmc81 Juniormester
29. december 2016 - 23:48 Der er 40 kommentarer

hente fra samme tabel to gange og derefter fra en anden tabel i samme query

Hej med jer

Endnu en gang må jeg ty til ekspertenes hjælp efter at have rodet med det i mange timer nu.

Jeg skal have listet kommende quiz for de næste 10 dage (quiznavn og startdato) og det skal gøres fra to tabeller.

Tabel 1 "postmeta" har felterne:  meta_id, post_id, meta_key, meta_value

Tabel 2 "quiz_master har felterne: id, name, text (og en masse andre uden betydning)

Når en quiz bliver oprettet i databasen, bliver det fordelt over de to tabeller. I "quiz_master" står der navn, beskrivelse og en masse andre ting. I tabellen "postmeta" bliver der oprettet quiz_id for quizzen i en række, startdato for samme quiz i en anden række og slutdato for samme quiz i en tredje række.  Altså bliver der oprettet en række i tabellen "quiz_master" og tre rækker i tabellen "postmeta" når en quiz bliver lavet.

I de tre rækker der bliver oprettet i tabellen "postmeta" indeholder felterne:

meta_id: unikke værdier
post_id: den samme værdi
meta_key: quiz_id, start_date, end_date
meta_value: værdien af meta_key

Et eksempel på oprettelse af en quiz kan være:

I quiz_master:
id = '111'  name = 'den bedste quiz'  text = 'Quizzen som har de bedste spørgsmål'  osv. 


De tre rækker i "postmeta":
meta_id = '2184'  post_id = '1063'  meta_key = 'quiz_id'  meta_value = '111'
meta_id = '2185'  post_id = '1063'  meta_key = 'start_date'  meta_value = '29-12-2016'
meta_id = '2186'  post_id = '1063'  meta_key = 'end_date'  metavalue = '05-01-2017'

Altså vil al info om denne quiz være:

quiz_id: 111
Navn: Den bedste quiz
Text: Quizzen som har de bedste spørgsmål
Start: 29-12-2016
Slut: 05-01-2017

Så jeg forestiller mig at man bruge SELECT as, Join og DATE BETWEEN i queryen, men jeg kan ikke begribe hvordan jeg skal skrive queryen, når den først skal:
- hente rækkerne med de ønskede datoer fra tabellen "postmeta"
- tage post_id fra de rækker
- hente rækkerne hvor post_id = samme post_id  og  meta_key = quiz_id  fra samme tabel (postmeta)
- hente quiz navn og text fra tabellen "quizmaster"

Håber der er garvet der kan se løsningen.

Med venlig hilsen

Kenneth Christiansen
Avatar billede arne_v Ekspert
30. december 2016 - 01:22 #1
Du skal have en self join !
Avatar billede arne_v Ekspert
30. december 2016 - 01:27 #2
Utestet:

SELECT quiz_master.id,quiz_master.name,quiz_master.text,pm2.meta_value,pm3.meta_value
FROM quiz_master
JOIN postmeta pm1 ON pm1.meta_key='quiz_id' AND pm1.meta_value=quiz_master.id
JOIN postmeta pm2 ON  pm2.meta_key='start_date' AND pm2.post_id=pm1.post_id
JOIN postmeta pm3 ON  pm3.meta_key='end_date' AND pm3.post_id=pm1.post_id
Avatar billede arne_v Ekspert
30. december 2016 - 01:28 #3
Og saa vil jeg kraftigt opfordre til en aendring af tabel struktur. Den der struktur goer bare alting unoedvendigt besvaerligt.
Avatar billede kmc81 Juniormester
30. december 2016 - 01:52 #4
Hej Arne. Tak for det jeg prøvet om jeg kan få strikket det sammen ved hjælp af din kode.
Grunden til tabel strukturen ser ud som den gør er, at det ikke kun er quiz, som er registreret i postmeta tabellen. Når det så er sagt, så vil jeg give dig ret i at den skulle laves om. Evt. så det hele trækkes ud fra en tabel. Problemet ligger dog i at den er sammenkædet med en app og det er ikke mig der har lavet hverken app eller databasen. Jeg skal blot have hentet info fra denne database.
Men prøver om jeg ikke kan få det til at fungere.
Avatar billede kmc81 Juniormester
30. december 2016 - 05:05 #5
Jeg kan ikke få det til at fungere. Jeg har prøvet med din kode og der vil den godt skrive id, navn og text ud men ikke start_date.  (end_date/pm3 har jeg fjernet, da ikke er nødvendigt)
Jeg har prøvet at tilføre en SELECT indeni i håb om at kunne trække start_date ud, men uden held. Hvordan kan jeg få trukket startdatoen ud?

Nogen idéer?

Det ser sådan ud nu:

$results_quiz = $pdo->query("SELECT quiz_master.id,quiz_master.name,quiz_master.text,pm2.meta_value,
(SELECT meta_value FROM postmeta WHERE postmeta.meta_key = 'startdate') AS startdato
FROM quiz_master
JOIN postmeta pm1 ON pm1.meta_key='quiz_id' AND pm1.meta_value=quiz_master.id
JOIN postmeta pm2 ON pm2.meta_key='start_date' AND pm2.post_id=pm1.post_id");
Avatar billede arne_v Ekspert
30. december 2016 - 15:00 #6
Hvad giver:

$results_quiz = $pdo->query("SELECT quiz_master.id,quiz_master.name,quiz_master.text,pm2.meta_value
FROM quiz_master
JOIN postmeta pm1 ON pm1.meta_key='quiz_id' AND pm1.meta_value=quiz_master.id
JOIN postmeta pm2 ON pm2.meta_key='start_date' AND pm2.post_id=pm1.post_id");

i resultat data?

Eller:

$results_quiz = $pdo->query("SELECT quiz_master.id AS id,quiz_master.name AS name,quiz_master.text AS text,pm2.meta_value AS start_date
FROM quiz_master
JOIN postmeta pm1 ON pm1.meta_key='quiz_id' AND pm1.meta_value=quiz_master.id
JOIN postmeta pm2 ON pm2.meta_key='start_date' AND pm2.post_id=pm1.post_id");
Avatar billede arne_v Ekspert
30. december 2016 - 15:00 #7
Er pm2.meta_key='start_date' den rigtige vaerdi?
Avatar billede kmc81 Juniormester
30. december 2016 - 16:26 #8
Ja pm2.meta_key='start_date' er den rigtige værdi og med den sidste kode du skrev henter den også start datoen :-)
Så skal vi bare have den til at kun at hente de rækker som ligger 10 dage frem fra nu.
Avatar billede arne_v Ekspert
30. december 2016 - 16:59 #9
Noget a la:

$results_quiz = $pdo->query("SELECT quiz_master.id AS id,quiz_master.name AS name,quiz_master.text AS text,pm2.meta_value AS start_date
FROM quiz_master
JOIN postmeta pm1 ON pm1.meta_key='quiz_id' AND pm1.meta_value=quiz_master.id
JOIN postmeta pm2 ON pm2.meta_key='start_date' AND pm2.post_id=pm1.post_id
WHERE pm2.meta_value < :cutoffdate");

?
Avatar billede arne_v Ekspert
30. december 2016 - 17:00 #10
Hmmm. Maaske skal der konverteres fra VARCHAR tiL DATETIME for at det virker.
Avatar billede arne_v Ekspert
30. december 2016 - 17:01 #11
Hvad database er det?

Funktioner for at konvertere fra VARCHAR tiL DATETIME er database specifikke.
Avatar billede kmc81 Juniormester
30. december 2016 - 17:23 #12
Er der en måde jeg kan se databasens type i phpmyadmin?
Avatar billede arne_v Ekspert
30. december 2016 - 17:33 #13
Ah - det er MySQL.

:-)
Avatar billede arne_v Ekspert
30. december 2016 - 17:37 #14
proev foerst med:

WHERE pm2.meta_value < DATE_ADD(NOW(), INTERVAL 10 DAY)

og hvis det ikke virker saa skal vi igang med at finde en funktion.

Foerste forsoeg:

WHERE DATE(pm2.meta_value) < DATE_ADD(NOW(), INTERVAL 10 DAY)
Avatar billede kmc81 Juniormester
30. december 2016 - 17:49 #15
Hehe. Jeg tænkte at da jeg havde lagt indlægget under MySQL var du nok klar over at det var det, så jeg troede du var ude i om det var " flat file data model", "hierarchical database model" eller "network database model"  :-D
Anyway, ingen af de to virker.. Den henter stadig alle quiz
Avatar billede kmc81 Juniormester
30. december 2016 - 18:03 #16
Undskyld min fejl. Den henter ikke noget, når jeg bruger de to ovenstående WHERE.
Avatar billede kmc81 Juniormester
30. december 2016 - 18:08 #17
Vi har denne kode at gå ud fra.. Her virker det sådan at den henter alle quiz med, id navn, text og start_date:

$results_quiz = $pdo->query("SELECT quiz_master.id AS id,quiz_master.name AS name,quiz_master.text AS text,pm2.meta_value AS start_date
FROM quiz_master
JOIN postmeta pm1 ON pm1.meta_key='quiz_id' AND pm1.meta_value=quiz_master.id
JOIN postmeta pm2 ON pm2.meta_key='start_date' AND pm2.post_id=pm1.post_id");
Avatar billede kmc81 Juniormester
30. december 2016 - 18:22 #18
Er det ikke noget ala: CONVERT( VARCHAR (), postmeta.meta_value, 103  )  der skal sættes ind?
Avatar billede arne_v Ekspert
30. december 2016 - 18:26 #19
Jo. Hvis databasen er MS SQLServer.

:-)
Avatar billede arne_v Ekspert
30. december 2016 - 18:30 #20
Men saa maa man jo igang paa den haarde maade.

Proev:

WHERE DATE(CONCAT(SUBSTR(pm2.meta_value,7,4),'-',SUBSTR(pm2.meta_value,4,2),'-'SUBSTR(pm2.meta_value,1,2)) < DATE_ADD(NOW(), INTERVAL 10 DAY)
Avatar billede kmc81 Juniormester
30. december 2016 - 18:47 #21
Den henter intet :-(

Kan man ikke ændre det oppe i SELECT som f.eks.:

SELECT quiz_master.id AS id,quiz_master.name AS name,quiz_master.text AS text, DATE_FORMAT(STR_TO_DATE('pm2.meta_value', '%e-%c-%Y'), '%Y-%c-%e') AS start_date ?
Avatar billede kmc81 Juniormester
30. december 2016 - 18:50 #22
Skulle måske lige sige at jeg har prøvet med dette også, men der henter den bare ikke start_date, men tænkte at jeg måske har skrevet det forkert.
Avatar billede arne_v Ekspert
30. december 2016 - 18:52 #23
DATE_FORMAT of STR_TO_DATE kan ogsaa bruges i.s.f. DATE, CONCAT og SUBSTR.

Men skal du have udvalgt raekker, saa skal det ned i WHERE.

Og der skal ikke '' omkring pm2.meta_value.
Avatar billede arne_v Ekspert
30. december 2016 - 18:52 #24
Jeg er lidt handikappet af ikke at vaere i naerheden af en MySQL, saa jeg kan ikke teste.
Avatar billede kmc81 Juniormester
30. december 2016 - 19:06 #25
Jeg er klar over at man udvælger rækkerne i WHERE, men tænkte at man måske kunne konvertere VARCHAR til DATE  i SELECT

Den laver fejl med dette. Hvad skal ændres for at det står rigtigt:

DATE_FORMAT(STR_TO_DATE(pm2.meta_value,7,4),'-',STR_TO_DATE(pm2.meta_value,4,2),'-'STR_TO_DATE(pm2.meta_value,1,2)) < DATE_ADD(NOW(), INTERVAL 10 DAY)
Avatar billede kmc81 Juniormester
30. december 2016 - 19:55 #26
Når du har mulighed for at teste det (og hvis du har lyst naturligvis) er du velkommen til at vende tilbage. Jeg tror jeg smider håndklædet i ringen for i dag. Mine øjne er ved at blive firkantede og jeg tænker ikke klart mere. Har nu prøvet med alle mulige ændringer og forsøg på at få det til at virke, men uden held.

Andre er selvfølgelig velkommen til at byde ind, hvis løsningen er øjensynlig. :-)

Rigtig godt nytår til alle.
Avatar billede arne_v Ekspert
31. december 2016 - 04:17 #27
Saa vidt jeg kan se saa boer:

WHERE DATE(CONCAT(SUBSTR(pm2.meta_value,7,4),'-',SUBSTR(pm2.meta_value,4,2),'-',SUBSTR(pm2.meta_value,1,2)) < DATE_ADD(NOW(), INTERVAL 10 DAY)

virke (jeg har kun tilfoejet et manglende komma).

Hvis altsaa logikken er rigtig: find raekker hvor start dato ligger laengere ude i fremtiden end nu + 10 dage.
Avatar billede kmc81 Juniormester
31. december 2016 - 15:09 #28
Den henter ingenting med ovenstående og jeg har sikret mig at der ligger en quiz med '03-01-2017' som værdi i meta_value :-)
Avatar billede kmc81 Juniormester
31. december 2016 - 15:20 #29
Hvad står værdierne for inde i SUBSTR (7,4 og 4,2 og 1,2)?
Avatar billede arne_v Ekspert
31. december 2016 - 16:00 #30
start og length
Avatar billede arne_v Ekspert
31. december 2016 - 16:01 #31
'03-01-2017'  skal ikke tages med. Den er ikke stoerrre end nu+10 dage
Avatar billede kmc81 Juniormester
31. december 2016 - 17:24 #32
Det kan være at jeg ikke fik forklaret det godt nok. Det skulle gerne være sådan at den henter fra i dag og til og med 10 dage frem.
Jeg har ændret datoen til 09-01-2017  og har også en der hedder 10-01-2017 for at se,  men den henter ingenting?
Avatar billede arne_v Ekspert
31. december 2016 - 20:33 #33
Saa skal det vel vaere:

WHERE DATE(CONCAT(SUBSTR(pm2.meta_value,7,4),'-',SUBSTR(pm2.meta_value,4,2),'-',SUBSTR(pm2.meta_value,1,2))  BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 10 DAY)
Avatar billede arne_v Ekspert
31. december 2016 - 20:35 #34
Kan du proeve og lave disse queries i PHPMyAdmin og se om de ser OK ud?

SELECT NOW(),DATE_ADD(NOW(), INTERVAL 10 DAY)

SELECT DATE(CONCAT(SUBSTR(meta_value,7,4),'-',SUBSTR(meta_value,4,2),'-',SUBSTR(meta_value,1,2))
FROM postmeta
WHERE meta_key='start_date'
Avatar billede kmc81 Juniormester
01. januar 2017 - 17:45 #35
Den skriver ingenting ud med koden fra #33.

med: SELECT NOW(),DATE_ADD(NOW(), INTERVAL 10 DAY)  skriver den datoen nu ud og 10 dage frem.

med: SELECT DATE(CONCAT(SUBSTR(meta_value,7,4),'-',SUBSTR(meta_value,4,2),'-',SUBSTR(meta_value,1,2))
FROM postmeta
WHERE meta_key='start_date'

skriver den:

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM postmeta WHERE meta_key='start_date' LIMIT 0,30' at line 1
Avatar billede arne_v Ekspert
01. januar 2017 - 19:22 #36
Mystisk.

Hvilken version af MySQL bruger du?
Avatar billede kmc81 Juniormester
01. januar 2017 - 21:08 #37
MySQL v. 5.6.33-cll-lve
Avatar billede kmc81 Juniormester
04. januar 2017 - 18:37 #38
Jeg har omsider fået den til at hente quiz for de næste 10 dage med denne sql:

$results_quiz = $pdo->query("SELECT qm.id, qm.name, qm.text, pm2.meta_value as start_date FROM quiz_master AS qm JOIN postmeta pm1 ON pm1.meta_key = 'quiz_id' AND pm1.meta_value = qm.id JOIN postmeta pm2 ON pm2.meta_key = 'start_date' AND pm2.post_id = pm1.post_id WHERE STR_TO_DATE(pm2.meta_value,'%d.%m.%Y')>CURDATE() ORDER BY STR_TO_DATE(pm2.meta_value,'%d-%m-%Y') ASC LIMIT 10");

Nu mangler jeg bare at få konverteret datoen så den ser således ud '04.01.2017' i stedet for '04-01-2017'
Avatar billede kmc81 Juniormester
04. januar 2017 - 18:53 #39
Arg. Det er så ikke helt sandt. Den printer selvfølgelig kun de første 10 quiz fra dagen efter d.d.  Jeg har prøvet med INTERVAL 10 DAYS i stedet for LIMIT 10, men det vil den ikke. Nogen forslag?
Avatar billede kmc81 Juniormester
04. januar 2017 - 20:07 #40
Jeg har valgt at holde mig til denne simple løsning, da den dækker mit behov. Den henter de næste 10 quiz fra i morgen og det er helt fint. Tak for kampen arne_v du hjalp mig godt på vej. :-)

$results_quiz = $pdo->query("SELECT qm.id, qm.name, qm.text, pm2.meta_value as start_date FROM quiz_master AS qm JOIN postmeta pm1 ON pm1.meta_key = 'quiz_id' AND pm1.meta_value = qm.id JOIN postmeta pm2 ON pm2.meta_key = 'start_date' AND pm2.post_id = pm1.post_id WHERE STR_TO_DATE(pm2.meta_value,'%d-%m-%Y')>CURDATE() ORDER BY STR_TO_DATE(pm2.meta_value,'%d-%m-%Y') LIMIT 10");
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

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