Я думаю, что это вне меня, я хочу преобразовать мой запрос MYSQL, чтобы он отображал строки и столбцы точно так же:
Это то, что я создал с запросом MYSQL:
Вот фактический запрос для создания этого:
SELECT h.workdate AS `Date` , DAYNAME(h.workdate) AS `Day` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='AM' AND DriverDock = 'Driv' AND `Salary Code Description` LIKE '%Perm%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `AMPERMDRIV` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='AM' AND DriverDock = 'Dock' AND `Salary Code Description` LIKE '%Perm%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `AMPERMDOCK` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='AM' AND DriverDock = 'Driv' AND `Salary Code Description` LIKE '%Cas%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `AMCASUDRIV` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='AM' AND DriverDock = 'Dock' AND `Salary Code Description` LIKE '%Cas%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `AMCASUDOCK` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='AM' AND DriverDock = 'Driv' AND `Salary Code Description` LIKE '%AGENT%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `AMAGENTDRIV` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='AM' AND DriverDock = 'Dock' AND `Salary Code Description` LIKE '%AGENT%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `AMAGENTDOCK` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='PM' AND DriverDock = 'Driv' AND `Salary Code Description` LIKE '%Perm%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `PMPERMDRIV` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='PM' AND DriverDock = 'Dock' AND `Salary Code Description` LIKE '%Perm%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `PMPERMDOCK` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='PM' AND DriverDock = 'Dock' AND `Salary Code Description` LIKE '%Cas%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `PMCASUDOCK` , COALESCE(TRUNCATE(SUM( CASE WHEN (shift='PM' AND DriverDock = 'Dock' AND `Salary Code Description` LIKE '%AGENT%') THEN CASE WHEN paycode IN ('03 Overtime 2.0') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 2.0) WHEN paycode IN ('02 Overtime 1.5') THEN (employeehours * IF(p.`Other Rate`=0,p.`Base Rate`,p.`Other Rate`) * 1.5) WHEN paycode IN ('01 Ordinary') THEN (employeehours * p.`Base Rate`) END END ),2),0) AS `PMAGENTDOCK` FROM employeedata d JOIN employeehours h ON d.`ID Number` = h.employeeid JOIN historyemployeepay p ON (h.employeeid = p.EmployeeID) AND (h.workdate >= p.FromDate) AND (h.workdate <= p.ToDate OR p.ToDate IS NULL) CROSS JOIN otherrates r WHERE DAYNAME(h.workdate) <> 'Saturday' GROUP BY h.workdate
У меня есть следующая таблица html, как я прохожу через результаты запроса и правильно отображаю ?:
<?php $querydailyoperations=mysql_query(" QUERY ABOVE "); while($querydailyoperationsshow=mysql_fetch_array($querydailyoperations)){ echo "??????????";}; ?>
а также:
<tr><td class="greencell">AM</td><td class="greencell">PERMANENT</td><td class="greencell">DRIVER</td>5x td here, input from above query... </tr> <tr><td class="greencell">AM</td><td class="greencell">PERMANENT</td><td class="dbluecell">DH</td> etc... </tr> <tr><td class="greencell">AM</td><td class="orangecell">CASUAL</td><td class="greencell">DRIVER</td> etc... </tr> <tr><td class="greencell">AM</td><td class="orangecell">CASUAL</td><td class="dbluecell">DH</td> etc... </tr> <tr><td class="greencell">AM</td><td nowrap class="redcell">AGENT LABOUR</td><td class="greencell">DRIVER</td> etc... </tr> <tr><td class="greencell">AM</td><td nowrap class="redcell">AGENT LABOUR</td><td class="dbluecell">DH</td> etc... </tr> <tr><td class="bluecell">PM</td><td class="greencell">PERMANENT</td><td class="greencell">DRIVER</td> etc... </tr> <tr><td class="bluecell">PM</td><td class="greencell">PERMANENT</td><td class="dbluecell">DH</td> etc... </tr> <tr><td class="bluecell">PM</td><td class="orangecell">CASUAL</td><td class="dbluecell">DH</td> etc... </tr> <tr><td class="bluecell">PM</td><td nowrap class="redcell">AGENT LABOUR</td><td class="dbluecell">DH</td> etc... </tr> </tbody> </table>
Получить результат можно с помощью SQL-запроса, но это не тривиально.
Но прежде чем идти по этому маршруту, я рекомендую вам рассмотреть другой подход.
Поскольку запрос возвращает относительно небольшой набор строк, вы можете вместо этого получить весь набор результатов в 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 и получить двухмерный массив, затем пропустить массив и получить значения по столбцам, а не по строкам. Один из вариантов – преобразовать полученный массив в новые массивы, которые выглядят следующим образом:
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' } }
Для небольшого набора строк, как у вас, я бы предпочел сделать это в PHP, а не в SQL.
Но вы спросили, как это сделать в SQL. Как я сказал ранее, это не тривиально.
SQL требует, чтобы оператор SELECT определял каждый возвращаемый столбец; число и типы столбцов не могут быть dymanic, когда выполняется оператор.
Если мы построим другой запрос (кроме исходного запроса), который определяет столбцы, и возвращает строки, которые, как мы ожидаем, возвращаются с помощью заполнителей для значений, мы находимся на полпути. Остается только выполнить внешнее соединение с строками, возвращаемыми исходным запросом, и условно вернуть значения столбцов в соответствующие строки.
Этот подход работает, если у вас есть предопределенный набор строк и столбцов, которые нам нужны, особенно если исходный источник строк разрежен, и нам нужно создать «отсутствующие» строки. (Например, при подсчете количества заказанных товаров и много недостающих строк, нет хорошего способа генерации недостающих строк.
Например:
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
Итак, это дает нам все определенные столбцы и все строки, которые мы хотим вернуть. Первый столбец заполнен. Этот запрос на самом деле не нужен GROUP BY, но нам понадобится его, как только мы сопоставим с строками из «реального» исходного набора результатов.
Теперь «трюк» сопоставляет строки из нашего источника и возвращает значение из столбца на основе соответствующих условий.
То, что мы собираемся генерировать, по существу, – это набор результатов, который выглядит следующим образом:
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
GROUP BY on. Мы собираемся использовать агрегатную функцию (MAX или SUM), используя преимущества обработки, которые они выполняют с значениями NULL, чтобы получить такой результат:
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
в вышеприведенном запросе может быть заменен встроенным представлением, обертывая парсеры вокруг подходящего запроса, который возвращает нужные нам строки.
Встроенное представление aliased как r
является нашим источником для возврата строк, которые мы хотим вернуть.
Выражения в списке SELECT выполняют условные тесты, чтобы выбрать правильные значения для каждого столбца в каждой строке.
Учитывая регулярную структуру операторов CASE, можно использовать некоторый SQL, чтобы помочь сгенерировать запрос, но это нужно сделать как отдельный шаг. Вывод из этого SQL может использоваться, чтобы помочь сформировать необходимый нам запрос.
В вашем случае, учитывая, что workdate
– это то, что вы хотите использовать для заголовка столбца, это, скорее всего, придется динамически генерировать. (Вы можете удалить столбец второго столбца «день недели» из исходного исходного запроса и перенести его на внешний запрос.
Если бы я не знал значения workdate
для заголовков, прежде чем я запустил запрос, я бы предпочел создать TEMPORARY TABLE и заполнить его результатами из исходного запроса, а затем запросить временную таблицу, чтобы получить заголовки workdate
, и «первый столбец» для создания строк. Затем я запустил бы фактический запрос против временной таблицы.
Повторяю, я думаю, вам будет лучше делать преобразование / поворот результатов из вашего исходного запроса в PHP, вместо того, чтобы пытаться это сделать в SQL.
Вы можете попробовать GROUP_CONCAT
Также упоминаются здесь Transpose Rows to Headers в MYSQL и здесь Основы сводной таблицы: строки в столбцы