Det är möjligt att få resultatet med en SQL-fråga, men det är inte trivialt.
Men innan du går den vägen rekommenderar jag att du överväger ett annat tillvägagångssätt.
Eftersom frågan returnerar en relativt liten uppsättning rader kan du istället hämta hela resultatuppsättningen i PHP som en tvådimensionell array.
Betrakta ett ganska enkelt fall, som en illustration:
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
Vi skulle kunna göra en fetchAll och få en tvådimensionell array, sedan loopa genom arrayen och hämta värdena kolumnvis, snarare än radvis. Ett alternativ är att omvandla arrayen vi tar emot till en ny array som ser ut så här:
bar ABC DEF
--- --- ---
fee 2 11
fi 3 13
fo 5 17
fum 7 19
Det är egentligen inte nödvändigt att göra omvandlingen, du kan gå den ursprungliga arrayen. Men att separera omvandlingen som ett separat steg skulle förmodligen göra din kod lite lättare när du faktiskt kommer till att generera utdata på sidan. (Det verkar vara ett tillräckligt vanligt problem att någon förmodligen har skrivit en funktion som gör den arraytransformation du vill ha. Jag tror inte att det finns en PHP-inbyggd som gör det.
rubriker:
array { [0]=>'bar' [1]=>'ABC' [2]=>'DEF' }
rader:
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' }
}
För en liten uppsättning rader som du har, skulle jag välja att göra detta i PHP snarare än i SQL.
Men du frågade hur man gör det i SQL. Som jag sa tidigare, det är inte trivialt.
SQL kräver att SELECT-satsen definierar varje kolumn som ska returneras; antalet och typerna av kolumnerna kan inte vara dynamiska när satsen körs.
Om vi bygger en annan fråga (förutom den ursprungliga frågan) som definierar kolumnerna och returnerar de rader som vi förväntar oss returnerade med platshållare för värdena, är vi halvvägs där. Allt som återstår är att göra en yttre koppling till raderna som returneras av den ursprungliga frågan, och villkorligt returnera kolumnvärdena på lämpliga rader.
Det här tillvägagångssättet fungerar om du har en fördefinierad uppsättning rader och kolumner som vi behöver returneras, särskilt när den ursprungliga radkällan är gles, och vi måste generera de "saknade" raderna. (Till exempel att få antalet beställda produkter och det finns många saknade rader, det finns inte ett bra sätt att generera de saknade raderna.
Till exempel:
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
Det kommer att returnera:
bar ABC DEF
--- --- ---
fee
fi
fo
fum
Så det får oss alla kolumner definierade och alla rader vi vill returnera. Den första kolumnen är ifylld. Den frågan behöver egentligen inte GROUP BY ännu, men vi kommer att behöva den när vi matchar raderna i den "riktiga" källresultatuppsättningen.
"Knepet" nu är att matcha raderna från vår källa och returnera värdet från en kolumn baserat på lämpliga villkor.
Vad vi kommer att generera är i huvudsak en resultatuppsättning som ser ut så här:
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
Sedan ska vi "komprimera" raderna genom att ta bort foo-kolumnen från resultatuppsättningen och göra en GROUP BY på bar
. Vi kommer att använda en aggregatfunktion (antingen MAX eller SUM) och dra nytta av hanteringen de gör med NULL-värden, för att producera ett resultat som detta:
bar foo ABC DEF
--- --- --- ---
fee 2 11
fi 3 13
fo 5 15
fum 7 17
Använder denna ganska svårhanterliga 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
Observera att mysource
i frågan ovan kan ersättas med en inline-vy, linda parens runt en lämplig fråga som returnerar de rader vi vill ha.
Den infogade vyn alias som r
är vår källa för att returnera de rader vi vill returnera.
Uttrycken i SELECT-listan gör de villkorliga testerna för att välja ut rätt värden för varje kolumn i varje rad.
Med tanke på det vanliga mönstret för CASE-satserna är det möjligt att använda lite SQL för att generera frågan, men det måste göras som ett separat steg. Utdata från den SQL kan användas för att skapa den faktiska fråga vi behöver.
I ditt fall, givet det workdate
är vad du vill använda för kolumnrubriken, kommer detta sannolikt att behöva genereras dynamiskt. (Du kan ta bort den andra kolumnen "veckodag"-kolumnen från den ursprungliga källfrågan och flytta den till den yttre frågan.
Om jag inte visste workdate
värden för rubrikerna innan jag körde frågan, då skulle jag välja att skapa en TILLFÄLLIG TABELL och fylla i den med resultat från den ursprungliga frågan och sedan fråga den temporära tabellen för att få workdate
rubriker och den "första kolumnen" för att generera raderna. Sedan körde jag den faktiska frågan mot den tillfälliga tabellen.
För att upprepa, jag tror att det är bättre att du transformerar/pivoterar resultaten från din ursprungliga fråga i PHP, istället för att försöka göra det i SQL.