Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Zapytanie PHP i Mysql, użyj PHP do konwersji wierszy na kolumny

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Przekazywanie nazwy kolumny jako parametru w funkcji przechowywanej mysql

  2. Jak uzyskać strukturę tabeli MySQL w PHP? Plus lista wszystkich stołów?

  3. Połącz dwie kolumny, wiele wierszy ignorując duplikaty - MySQL

  4. Funkcja MySQL GeoSpatial dla ST_Distance_Spheroid? Metryka użyta w zamian Rodzaj GLength?

  5. Masz problemy z przyłączeniem MySQL, które musi spełniać wiele warunków