É possível obter o resultado usando uma consulta SQL, mas não é trivial.
Mas antes de seguir esse caminho, recomendo que você considere uma abordagem diferente.
Como a consulta está retornando um conjunto relativamente pequeno de linhas, você pode recuperar todo o conjunto de resultados no PHP como um array bidimensional.
Considere um caso bastante simples, como ilustração:
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
Poderíamos fazer um fetchAll e obter um array bidimensional, depois percorrer o array e recuperar os valores em coluna, em vez de linha. Uma opção é transformar o array que recebemos em um novo array parecido com este:
bar ABC DEF
--- --- ---
fee 2 11
fi 3 13
fo 5 17
fum 7 19
Não é realmente necessário fazer a transformação, você pode andar no array original. Mas separar a transformação como uma etapa separada provavelmente tornaria seu código um pouco mais fácil, quando você realmente gerar a saída na página. (Parece um problema bastante comum que alguém provavelmente escreveu uma função que faz a transformação de array que você deseja. Eu não acho que exista um PHP embutido que faça isso.
títulos:
array { [0]=>'bar' [1]=>'ABC' [2]=>'DEF' }
linhas:
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' }
}
Para um pequeno conjunto de linhas como você tem, eu optaria por fazer isso no PHP em vez de no SQL.
Mas você perguntou como fazer isso no SQL. Como eu disse anteriormente, não é trivial.
SQL requer que a instrução SELECT defina cada coluna a ser retornada; o número e os tipos das colunas não podem ser dinâmicos quando a instrução é executada.
Se construirmos outra consulta (além da consulta original) que defina as colunas e retorne as linhas que esperamos que sejam retornadas com espaços reservados para os valores, estaremos na metade do caminho. Tudo o que resta é fazer uma junção externa às linhas retornadas pela consulta original e retornar condicionalmente os valores das colunas nas linhas apropriadas.
Essa abordagem funciona se você tiver um conjunto predefinido de linhas e colunas que precisamos retornar, especialmente quando a origem da linha original for esparsa e precisarmos gerar as linhas "ausentes". (Por exemplo, ao obter contagens de produtos pedidos e há muitas linhas ausentes, não há uma boa maneira de gerar as linhas ausentes.
Por exemplo:
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
Isso retornará:
bar ABC DEF
--- --- ---
fee
fi
fo
fum
Então, isso nos dá todas as colunas definidas e todas as linhas que queremos retornar. A primeira coluna é preenchida. Essa consulta ainda não precisa do GROUP BY, mas vamos precisar dele quando correspondermos às linhas do conjunto de resultados de origem "real".
O "truque" agora é combinar as linhas de nossa fonte e retornar o valor de uma coluna com base nas condições apropriadas.
O que vamos gerar, essencialmente, é um conjunto de resultados que se parece com isso:
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
Então vamos "recolher" as linhas, removendo a coluna foo do conjunto de resultados e fazendo um GROUP BY na
bar
. Vamos usar uma função agregada (seja MAX ou SUM) aproveitando o tratamento que eles fazem com valores NULL, para produzir um resultado como este:bar foo ABC DEF
--- --- --- ---
fee 2 11
fi 3 13
fo 5 15
fum 7 17
Usando este SQL bastante complicado:
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
Observe que
mysource
na consulta acima pode ser substituído por uma visualização inline, envolvendo parênteses em torno de uma consulta adequada que retorna as linhas que desejamos. A visualização em linha alias como
r
é nossa fonte para retornar as linhas que queremos retornar. As expressões na lista SELECT estão fazendo os testes condicionais, para escolher os valores corretos para cada coluna em cada linha.
Dado o padrão regular das instruções CASE, é possível usar algum SQL para ajudar a gerar a consulta, mas isso deve ser feito em uma etapa separada. A saída desse SQL pode ser usada para ajudar a formar a consulta real de que precisamos.
No seu caso, dado que
workdate
é o que você deseja usar para o cabeçalho da coluna, isso provavelmente terá que ser gerado dinamicamente. (Você pode remover essa segunda coluna 'dia da semana' da consulta de origem original e movê-la para a consulta externa. Se eu não souber a
workdate
valores para os títulos antes de executar a consulta, então optaria por criar uma TABELA TEMPORÁRIA e preenchê-la com os resultados da consulta original e, em seguida, consultar a tabela temporária para obter o workdate
cabeçalhos e a "primeira coluna" para gerar as linhas. Então eu executaria a consulta real na tabela temporária. Para repetir, acho que seria melhor fazer a transformação/pivot dos resultados de sua consulta original em PHP, em vez de tentar fazê-lo em SQL.