SQLクエリを使用して結果を取得することは可能ですが、それは簡単ではありません。
ただし、そのルートに進む前に、別のアプローチを検討することをお勧めします。
クエリは比較的小さな行のセットを返すため、代わりに結果セット全体を2次元配列としてPHPに取得できます。
例として、かなり単純なケースを考えてみましょう。
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
fetchAllを実行し、2次元配列を取得してから、配列をループして、行単位ではなく列単位で値を取得することができます。 1つのオプションは、受け取った配列を次のような新しい配列に変換することです。
bar ABC DEF
--- --- ---
fee 2 11
fi 3 13
fo 5 17
fum 7 19
変換を行う必要はありません。元の配列をウォークすることができます。ただし、変換を別のステップとして分離すると、実際にページに出力を生成するときに、コードが少し簡単になる可能性があります。 (誰かがあなたが望む配列変換を行う関数を書いたのは十分に一般的な問題のようです。それを行うPHPが組み込まれているとは思いません。
見出し:
array { [0]=>'bar' [1]=>'ABC' [2]=>'DEF' }
行:
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' }
}
あなたが持っているような小さな行のセットについては、SQLではなくPHPでこれを行うことを選択します。
しかし、あなたはSQLでそれを行う方法を尋ねました。前に言ったように、それは些細なことではありません。
SQLでは、SELECTステートメントで返されるすべての列を定義する必要があります。ステートメントの実行時に、列の数とタイプを動的にすることはできません。
列を定義する別のクエリ(元のクエリとは別に)を作成し、値のプレースホルダーとともに返されると予想される行を返す場合、その途中です。残っているのは、元のクエリによって返された行に対して外部結合を実行し、適切な行の列値を条件付きで返すことだけです。
このアプローチは、特に元の行ソースがスパースであり、「欠落している」行を生成する必要がある場合に、返される必要のある事前定義された行と列のセットがある場合に機能します。 (たとえば、注文された製品の数を取得し、欠落している行がたくさんある場合、欠落している行を生成する良い方法はありません。
例:
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
戻ります:
bar ABC DEF
--- --- ---
fee
fi
fo
fum
つまり、これですべての列が定義され、すべての行が返されます。最初の列にデータが入力されます。そのクエリにはまだGROUPBYは必要ありませんが、「実際の」ソース結果セットの行と一致したら、GROUPBYが必要になります。
「トリック」は、ソースからの行と一致し、適切な条件に基づいて列から値を返すようになりました。
生成するのは、基本的に次のような結果セットです。
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
次に、結果セットからfoo列を削除し、bar
でGROUPBYを実行して、行を「折りたたむ」ことにします。 。 NULL値で行う処理を利用して、集計関数(MAXまたはSUM)を使用して、次のような結果を生成します。
bar foo ABC DEF
--- --- --- ---
fee 2 11
fi 3 13
fo 5 15
fum 7 17
このかなり扱いにくい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
mysource
に注意してください 上記のクエリでは、インラインビューに置き換えることができ、必要な行を返す適切なクエリの周りに親をラップします。
r
としてエイリアスされたインラインビュー 返したい行を返すためのソースです。
SELECTリストの式は、各行の各列に適切な値を選択するために、条件付きテストを実行しています。
CASEステートメントの規則的なパターンを考えると、クエリの生成に役立つSQLを使用することは可能ですが、それは別のステップとして実行する必要があります。そのSQLからの出力は、必要な実際のクエリの作成に役立てることができます。
あなたの場合、そのworkdate
は列ヘッダーに使用するものです。これは動的に生成する必要がある可能性があります。 (その2番目の列の「曜日」列を元のソースクエリから削除し、それを外部クエリに移動することができます。
workdate
がわからなかった場合 クエリを実行する前の見出しの値、次にTEMPORARY TABLEを作成し、元のクエリの結果を入力してから、一時テーブルにクエリを実行して、workdate
を取得します。 ヘッダー、および行を生成するための「最初の列」。次に、一時テーブルに対して実際のクエリを実行します。
繰り返しになりますが、SQLで実行するよりも、PHPで元のクエリの結果の変換/ピボットを実行する方がよいと思います。