Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Truy vấn PHP và Mysql, sử dụng PHP để chuyển đổi hàng thành cột

Có thể nhận được kết quả bằng cách sử dụng truy vấn SQL, nhưng nó không phải là tầm thường.

Nhưng trước khi bạn đi theo con đường đó, tôi khuyên bạn nên xem xét một cách tiếp cận khác.

Vì truy vấn đang trả về một tập hợp hàng tương đối nhỏ, thay vào đó, bạn có thể truy xuất toàn bộ tập hợp kết quả vào PHP dưới dạng một mảng hai chiều.

Hãy xem xét một trường hợp khá đơn giản, như một minh họa:

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

Chúng ta có thể thực hiện một fetchAll và lấy một mảng hai chiều, sau đó lặp qua mảng và truy xuất các giá trị theo cột, thay vì theo hàng. Một tùy chọn là chuyển đổi mảng chúng tôi nhận được thành một mảng mới trông giống như sau:

bar  ABC  DEF
---  ---  ---
fee    2   11
fi     3   13
fo     5   17
fum    7   19

Nó không thực sự cần thiết để thực hiện chuyển đổi, bạn có thể đi bộ mảng ban đầu. Nhưng tách chuyển đổi ra thành một bước riêng biệt có thể sẽ làm cho mã của bạn dễ dàng hơn một chút, khi bạn thực sự tạo ra kết quả đầu ra vào trang. (Có vẻ như đây là một vấn đề đủ phổ biến mà ai đó có thể đã viết một hàm thực hiện chuyển đổi mảng mà bạn muốn. Tôi không nghĩ rằng có một nội trang PHP nào thực hiện được điều đó.

đề mục:

array { [0]=>'bar'  [1]=>'ABC'  [2]=>'DEF' }

hàng:

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' }
}

Đối với một nhóm nhỏ các hàng như bạn có, tôi sẽ chọn làm điều này trong PHP thay vì trong SQL.

Nhưng bạn đã hỏi làm thế nào để làm điều đó trong SQL. Như tôi đã nói trước đó, nó không hề tầm thường.

SQL yêu cầu câu lệnh SELECT xác định mọi cột được trả về; số lượng và loại cột không thể bị xáo trộn khi câu lệnh thực thi.

Nếu chúng ta xây dựng một truy vấn khác (ngoài truy vấn ban đầu) xác định các cột và trả về các hàng mà chúng ta mong đợi được trả về cùng với trình giữ chỗ cho các giá trị, thì chúng ta đã đi được nửa chặng đường. Tất cả những gì còn lại là thực hiện một phép nối bên ngoài vào các hàng được trả về bởi truy vấn ban đầu và trả về có điều kiện các giá trị cột trên các hàng thích hợp.

Cách tiếp cận này hoạt động nếu bạn có một tập hợp hàng và cột được xác định trước mà chúng tôi cần trả lại, đặc biệt khi nguồn hàng ban đầu thưa thớt và chúng tôi cần tạo các hàng "bị thiếu". (Ví dụ:nhận số lượng sản phẩm đã đặt hàng và có rất nhiều hàng bị thiếu, không có cách nào tốt để tạo các hàng bị thiếu.

Ví dụ:

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

Điều đó sẽ trở lại:

 bar  ABC  DEF
 ---  ---  ---
 fee
 fi
 fo
 fum

Vì vậy, điều đó giúp chúng ta xác định tất cả các cột và tất cả các hàng mà chúng ta muốn trả về. Cột đầu tiên được điền. Truy vấn đó chưa thực sự cần GROUP BY, nhưng chúng tôi sẽ cần nó khi chúng tôi khớp với các hàng trong tập kết quả nguồn "thực".

"Thủ thuật" bây giờ là khớp các hàng từ nguồn của chúng tôi và trả về giá trị từ một cột dựa trên các điều kiện thích hợp.

Những gì chúng ta sẽ tạo, về cơ bản là một tập kết quả trông giống như sau:

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

Sau đó, chúng tôi sẽ "thu gọn" các hàng, bằng cách xóa cột foo khỏi tập kết quả và thực hiện GROUP BY trên bar . Chúng tôi sẽ sử dụng một hàm tổng hợp (MAX hoặc SUM) tận dụng việc xử lý chúng thực hiện với các giá trị NULL, để tạo ra một kết quả như thế này:

bar  foo  ABC  DEF
---  ---  ---  ---
fee         2   11
fi          3   13
fo          5   15
fum         7   17

Sử dụng SQL khá khó sử dụng này:

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

Lưu ý rằng mysource trong truy vấn ở trên có thể được thay thế bằng một dạng xem nội tuyến, bao bọc xung quanh một truy vấn phù hợp trả về các hàng mà chúng ta muốn.

Chế độ xem nội tuyến có bí danh là r là nguồn của chúng tôi để trả về các hàng mà chúng tôi muốn trả lại.

Các biểu thức trong danh sách CHỌN đang thực hiện các bài kiểm tra điều kiện, để chọn ra các giá trị phù hợp cho mỗi cột trong mỗi hàng.

Với mẫu câu lệnh CASE thông thường, có thể sử dụng một số SQL để giúp tạo truy vấn, nhưng điều đó phải được thực hiện như một bước riêng biệt. Đầu ra từ SQL đó có thể được sử dụng để giúp hình thành truy vấn thực tế mà chúng tôi cần.

Trong trường hợp của bạn, với workdate đó là những gì bạn muốn sử dụng cho tiêu đề cột, điều này có thể sẽ phải được tạo động. (Bạn có thể bỏ cột 'ngày trong tuần' thứ hai đó khỏi truy vấn nguồn ban đầu và chuyển nó sang truy vấn bên ngoài.

Nếu tôi không biết workdate giá trị cho các tiêu đề trước khi tôi chạy truy vấn, sau đó tôi chọn tạo BẢNG TẠM THỜI và điền vào nó với các kết quả từ truy vấn ban đầu, sau đó truy vấn bảng tạm thời, để lấy workdate tiêu đề và "cột đầu tiên" để tạo các hàng. Sau đó, tôi sẽ chạy truy vấn thực tế đối với bảng tạm thời.

Để nhắc lại, tôi nghĩ bạn nên thực hiện chuyển đổi / xoay vòng các kết quả từ truy vấn ban đầu của bạn trong PHP, thay vì cố gắng thực hiện nó trong 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. Tính tuổi từ ngày sinh trong mysql

  2. PHP MySQL chèn truy vấn xây dựng mảng liên kết đa chiều từ các khóa mảng

  3. Đặt múi giờ kết nối với Spring và DBCP và MySQL

  4. MySQL và khóa bảng, đọc, sau đó cắt bớt

  5. Android JDBC không hoạt động:ClassNotFoundException trên trình điều khiển