Het is de bedoeling dat een 'closest event' en de daarop volgende worden weergeven.
Ik heb 2 tabellen. Één moet gewoon 'gejoint' zijn en de andere bevat de datums datum_start en datum_end.
Nou wil ik de data die het dichtst bij nu ligt (of een eigen datum) of wat in ieder geval tussen start en end valt. Maar ook de daarop volgende.
Dus nu en volgende. Zoiets als Nu&Straks van een tvgids.
Lastig uitgelegd, maar kan iemand me op weg helpen?
$sql = "
SELECT
ch.id,
ch.name,
ch.name_short,
pr.channel_id,
pr.db_id,
pr.titel,
pr.datum_start,
pr.datum_end
FROM
" . TABLE_PREFIX . "channels AS ch
LEFT JOIN
" . TABLE_PREFIX . "programs AS pr
ON ch.id = pr.channel_id
WHERE
pr.titel IS NOT NULL
AND (
CURRENT_DATE BETWEEN
pr.datum_start
AND
pr.datum_end
OR
pr.datum_start =
(
SELECT
MIN(pr.datum_start)
FROM
" . TABLE_PREFIX . "programs
WHERE
pr.datum_start > CURRENT_DATE
)
)
";
Geeft error: SQLSTATE[HY000]: General error: 1111 Invalid use of group function
Als je die subquery nu eens los uitvoert eenmalig voordat je deze query aanroept. Het resultaat ervan voeg je gewoon in. Werkt het dan wel goed? Ik kan me namelijk voorstellen dat die subquery veel te vaak aangeroepen gaat worden op deze manier (namelijk, voor elke rij).
Waarom is dat niet wat het moet zijn? Merk op dat CURRENT_DATE alleen de datum teruggeeft, niet de tijd!
Wat je wellicht kan doen is die subquery ombouwen tot een join en aan de hand daarvan filteren. Dan doe je de berekening maar 1 keer in elk geval. Overigens of het op die manier in een subquery echt voor elke rij gebeurt weet ik niet, maar dat is wel mijn vermoeden.
SELECT
ch.id,
ch.name,
ch.name_short,
pr.channel_id,
pr.db_id,
pr.datum_start,
pr.datum_end
FROM
" . TABLE_PREFIX . "channels AS ch
LEFT JOIN
" . TABLE_PREFIX . "programs AS pr
ON ch.id = pr.channel_id
INNER JOIN (
SELECT
datum_start
FROM
" . TABLE_PREFIX . "programs
WHERE
datum_start > CURRENT_DATE
ORDER BY
datum_start ASC
LIMIT 1
) a ON pr.datum_start = a.datum_start;
Snelle ombouw, zo'n omzetting van subquery naar join kan nogal eens wat anders zijn dan je in eerste instantie denkt, maar volgens mij zou dit moeten kunnen.
Toevoeging op 14/05/2014 11:56:28:
Alweer te laat :-)
Nu: 11:52
Het is bijna nooit 11:52:00, maar bijna altijd een paar seconden meer ;-)
Ik join eerst programs met als extra voorwaarde dat het nu bezig moet zijn (np = now_playing)
Daarna join ik programs (ne=next) nog eens met als extra voorwaarde dat de eindtijd van now_playing overkomt met de starttijd van next.
Je hebt alleen een 'probleem' als er op dit moment geen programma bezig is.
Nice :) Bedankt!
Dit betekent wel dat ik alle velden dubbel moet ophalen (Er zijn er nog meer)? Eenmaal voor np en eenmaal voor ne. Maar dat lijkt me niet zo'n performance probleem.
> Je hebt alleen een 'probleem' als er op dit moment geen programma bezig is.
Dat heb ik nu nog niet, maar zou natuurlijk ooit kunnen voorkomen. Ik kan natuurlijk in PHP even controleren of ie is geset en niet leeg is.
Als er voor één van beide geen programma is, wordt er niks weergegeven?
>>Dit betekent wel dat ik alle velden dubbel moet ophalen (Er zijn er nog meer)? Eenmaal voor np en eenmaal voor ne. Maar dat lijkt me niet zo'n performance probleem.
Het aantal kolommen in de SELECT heeft geen noemenswaardige invloed op de performance
>>Als er voor één van beide geen programma is, wordt er niks weergegeven?
Klopt.
Het kan wel met een left join, maar dan moet de tweede join met een subquery.