Je možné získat výsledek pomocí SQL dotazu, ale není to triviální.
Ale než se vydáte touto cestou, doporučuji vám zvážit jiný přístup.
Protože dotaz vrací relativně malou sadu řádků, můžete místo toho načíst celou sadu výsledků do PHP jako dvourozměrné pole.
Vezměme si jako ilustraci poměrně jednoduchý případ:
SELECT foo, fee, fi, fo, fum
FROM mytable
ORDER BY foo
foo fee fi fo fum
--- --- --- --- ---
ABC 2 3 5 7
DEF 11 13 17 19
Mohli bychom provést fetchAll a získat dvourozměrné pole, pak procházet polem a načíst hodnoty po sloupcích, nikoli po řádcích. Jednou z možností je transformovat pole, které obdržíme, na nové pole, které vypadá takto:
bar ABC DEF
--- --- ---
fee 2 11
fi 3 13
fo 5 17
fum 7 19
Není opravdu nutné provádět transformaci, můžete projít původní pole. Ale oddělení transformace jako samostatný krok by pravděpodobně trochu usnadnilo váš kód, když se dostanete ke skutečnému generování výstupu na stránku. (Vypadá to jako dost častý problém, že někdo pravděpodobně napsal funkci, která provádí požadovanou transformaci pole. Nemyslím si, že existuje vestavěný modul PHP, který by to dělal.
nadpisy:
array { [0]=>'bar' [1]=>'ABC' [2]=>'DEF' }
řádky:
array {
[0]=>array { [0]=>'fee' [1]=>'2' [2]=>'11' }
[1]=>array { [0]=>'fi' [1]=>'3' [2]=>'13' }
[2]=>array { [0]=>'fo' [1]=>'5' [2]=>'17' }
[3]=>array { [0]=>'fum' [1]=>'7' [2]=>'19' }
}
Pro malou sadu řádků, jako máte vy, bych se rozhodl to udělat v PHP spíše než v SQL.
Ale ptal jste se, jak to udělat v SQL. Jak jsem řekl dříve, není to triviální.
SQL vyžaduje, aby příkaz SELECT definoval každý sloupec, který má být vrácen; počet a typy sloupců nemohou být při provádění příkazu dynamické.
Pokud vytvoříme další dotaz (kromě původního dotazu), který definuje sloupce a vrátí řádky, které očekáváme, se zástupnými symboly pro hodnoty, jsme na půli cesty. Zbývá pouze provést vnější spojení s řádky vrácenými původním dotazem a podmíněně vrátit hodnoty sloupců na příslušných řádcích.
Tento přístup funguje, pokud máte předdefinovanou sadu řádků a sloupců, které potřebujeme vrátit, zvláště když je původní zdroj řádků řídký a potřebujeme vygenerovat „chybějící“ řádky. (Například, když získáte počty objednaných produktů a mnoho chybějících řádků, neexistuje dobrý způsob, jak chybějící řádky vygenerovat.
Například:
SELECT r.bar
, '' AS `ABC`
, '' AS `DEF`
FROM ( SELECT 'fee' AS bar
UNION ALL SELECT 'fi'
UNION ALL SELECT 'fo'
UNION ALL SELECT 'fum'
) r
GROUP BY r.bar
To se vrátí:
bar ABC DEF
--- --- ---
fee
fi
fo
fum
Takže dostaneme všechny definované sloupce a všechny řádky, které chceme vrátit. První sloupec je vyplněn. Tento dotaz zatím ve skutečnosti nepotřebuje GROUP BY, ale budeme ho potřebovat, jakmile se přiřadíme k řádkům ze "skutečné" zdrojové sady výsledků.
„Trik“ nyní spočívá v porovnávání řádků z našeho zdroje a vrácení hodnoty ze sloupce na základě vhodných podmínek.
To, co vygenerujeme, je v podstatě sada výsledků, která vypadá takto:
bar foo ABC DEF
--- --- --- ---
fee ABC 2
fee DEF 11
fi ABC 3
fi DEF 13
fo ABC 5
fo DEF 15
fum ABC 7
fum DEF 17
Poté řádky "sbalíme" odstraněním sloupce foo z výsledkové sady a provedením GROUP BY na bar
. Použijeme agregační funkci (buď MAX nebo SUM) s využitím manipulace, kterou provádějí s hodnotami NULL, k vytvoření výsledku, jako je tento:
bar foo ABC DEF
--- --- --- ---
fee 2 11
fi 3 13
fo 5 15
fum 7 17
Použití tohoto poněkud nepraktického SQL:
SELECT r.bar
, MAX(CASE WHEN t.foo = 'ABC' THEN CASE r.bar
WHEN 'fee' THEN t.fee
WHEN 'fi' THEN t.fi
WHEN 'fo' THEN t.fo
WHEN 'fum' THEN t.fum
END END) AS 'ABC'
, MAX(CASE WHEN t.foo = 'DEF' THEN CASE r.bar
WHEN 'fee' THEN t.fee
WHEN 'fi' THEN t.fi
WHEN 'fo' THEN t.fo
WHEN 'fum' THEN t.fum
END END) AS 'DEF'
FROM ( SELECT 'foo' AS col
UNION ALL SELECT 'fee'
UNION ALL SELECT 'fi'
UNION ALL SELECT 'fo'
UNION ALL SELECT 'fum'
) r
CROSS
JOIN mysource t
GROUP BY r.bar
Všimněte si, že mysource
ve výše uvedeném dotazu lze nahradit vloženým pohledem, který obklopí závorky kolem vhodného dotazu, který vrátí řádky, které chceme.
Vložený pohled s aliasem r
je naším zdrojem pro vrácení řádků, které chceme vrátit.
Výrazy v seznamu SELECT provádějí podmíněné testy, aby vybraly správné hodnoty pro každý sloupec v každém řádku.
Vzhledem k pravidelnému vzoru příkazů CASE je možné použít nějaké SQL k vygenerování dotazu, ale to musí být provedeno jako samostatný krok. Výstup z tohoto SQL lze použít k vytvoření skutečného dotazu, který potřebujeme.
Ve vašem případě s ohledem na workdate
je to, co chcete použít pro záhlaví sloupce, bude pravděpodobně muset být generováno dynamicky. (Tento druhý sloupec „den v týdnu“ můžete vypustit z původního zdrojového dotazu a přesunout jej do vnějšího dotazu.
Kdybych neznal workdate
hodnoty pro nadpisy před spuštěním dotazu, pak bych se rozhodl vytvořit TEMPORARY TABLE a naplnit ji výsledky z původního dotazu a poté dotazovat dočasnou tabulku, abych získal workdate
záhlaví a "první sloupec" pro generování řádků. Pak bych spustil skutečný dotaz proti dočasné tabulce.
Abych to zopakoval, myslím, že by bylo lepší provést transformaci/pivot výsledků z vašeho původního dotazu v PHP, než se o to pokoušet v SQL.