Możliwe jest uzyskanie wyniku za pomocą zapytania SQL, ale nie jest to trywialne.
Ale zanim pójdziesz tą trasą, radzę rozważyć inne podejście.
Ponieważ zapytanie zwraca stosunkowo mały zestaw wierszy, możesz zamiast tego pobrać cały zestaw wyników do PHP jako dwuwymiarową tablicę.
Rozważmy dość prosty przypadek, na przykład:
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
Moglibyśmy wykonać fetchAll i uzyskać dwuwymiarową tablicę, a następnie przejść przez tablicę i pobrać wartości w kolumnach, a nie w wierszach. Jedną z opcji jest przekształcenie otrzymanej tablicy w nowe tablice, które wyglądają tak:
bar ABC DEF
--- --- ---
fee 2 11
fi 3 13
fo 5 17
fum 7 19
Przekształcenie nie jest tak naprawdę konieczne, można przejść do oryginalnej tablicy. Ale oddzielenie transformacji jako oddzielnego kroku prawdopodobnie ułatwiłoby Twój kod, gdy faktycznie zaczniesz generować dane wyjściowe na stronie. (Wydaje się, że jest to dość powszechny problem, że ktoś prawdopodobnie napisał funkcję, która wykonuje transformację tablicy, którą chcesz. Nie sądzę, że istnieje wbudowane PHP, które to robi.
nagłówki:
array { [0]=>'bar' [1]=>'ABC' [2]=>'DEF' }
wiersze:
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' }
}
W przypadku małego zestawu wierszy, takich jak ty, wybrałbym to w PHP, a nie w SQL.
Ale pytałeś, jak to zrobić w SQL. Jak powiedziałem wcześniej, nie jest to trywialne.
SQL wymaga, aby instrukcja SELECT definiowała każdą zwracaną kolumnę; liczba i typy kolumn nie mogą być dynamiczne po wykonaniu instrukcji.
Jeśli zbudujemy inne zapytanie (oprócz oryginalnego zapytania), które definiuje kolumny i zwraca wiersze, które spodziewamy się zwrócić z symbolami zastępczymi dla wartości, jesteśmy w połowie drogi. Pozostaje tylko wykonać zewnętrzne sprzężenie z wierszami zwróconymi przez oryginalne zapytanie i warunkowe zwrócenie wartości kolumn w odpowiednich wierszach.
To podejście działa, jeśli masz wstępnie zdefiniowany zestaw wierszy i kolumn, które muszą zostać zwrócone, zwłaszcza gdy oryginalne źródło wiersza jest rzadkie i musimy wygenerować „brakujące” wiersze. (Na przykład, aby uzyskać liczbę zamówionych produktów i jest wiele brakujących wierszy, nie ma dobrego sposobu na wygenerowanie brakujących wierszy.
Na przykład:
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 powróci:
bar ABC DEF
--- --- ---
fee
fi
fo
fum
W ten sposób otrzymujemy wszystkie zdefiniowane kolumny i wszystkie wiersze, które chcemy zwrócić. Pierwsza kolumna jest wypełniona. To zapytanie tak naprawdę nie potrzebuje jeszcze opcji GROUP BY, ale będziemy jej potrzebować, gdy dopasujemy wiersze z „prawdziwego” zestawu wyników źródła.
„Sztuczka” polega teraz na dopasowaniu wierszy z naszego źródła i zwróceniu wartości z kolumny na podstawie odpowiednich warunków.
To, co zamierzamy wygenerować, to zasadniczo zestaw wyników, który wygląda tak:
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
Następnie „zwiniemy” wiersze, usuwając kolumnę foo z zestawu wyników i wykonując GROUP BY na bar
. Użyjemy funkcji agregującej (MAX lub SUM), korzystając z obsługi wartości NULL, aby uzyskać wynik taki jak ten:
bar foo ABC DEF
--- --- --- ---
fee 2 11
fi 3 13
fo 5 15
fum 7 17
Używając tego raczej nieporęcznego 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
Zwróć uwagę, że mysource
w powyższym zapytaniu można zastąpić widokiem wbudowanym, owijając nawiasy wokół odpowiedniego zapytania, które zwraca żądane wiersze.
Widok wbudowany aliasem r
jest naszym źródłem zwracania wierszy, które chcemy zwrócić.
Wyrażenia z listy SELECT wykonują testy warunkowe, aby wybrać właściwe wartości dla każdej kolumny w każdym wierszu.
Biorąc pod uwagę regularny wzorzec instrukcji CASE, możliwe jest użycie kodu SQL do pomocy w wygenerowaniu zapytania, ale musi to być zrobione jako osobny krok. Dane wyjściowe z tego SQL mogą być użyte do pomocy w stworzeniu zapytania, którego potrzebujemy.
W twoim przypadku, biorąc pod uwagę, że workdate
jest tym, czego chcesz użyć w nagłówku kolumny, prawdopodobnie będzie to musiało być generowane dynamicznie. (Można usunąć drugą kolumnę „dzień tygodnia” z oryginalnego zapytania źródłowego i przenieść ją do zapytania zewnętrznego.
Gdybym nie znał workdate
wartości dla nagłówków przed uruchomieniem zapytania, wtedy zdecydowałbym się utworzyć TABELĘ TYMCZASOWĄ i wypełnić ją wynikami z oryginalnego zapytania, a następnie wysłać zapytanie do tabeli tymczasowej, aby uzyskać workdate
nagłówki i „pierwsza kolumna”, aby wygenerować wiersze. Następnie uruchomiłbym rzeczywiste zapytanie w tabeli tymczasowej.
Powtarzam, uważam, że lepiej byłoby zrobić przekształcenie/przechylenie wyników z oryginalnego zapytania w PHP, zamiast próbować to zrobić w SQL.