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

Cách trả về tập hợp kết quả dựa trên các hàng khác

Đây là hai giải pháp khác nhau:(Lưu ý:Tôi đã gọi trường enum là "package_type")

Giải pháp đầu tiên (thông qua hàm IF ()):

select 
  i.location, 
  if(ps.id is not null, ps.id, pg.id) as package_id
from 
  (select distinct location from Items) i
  inner join 
    (select i.location, p.id
     from Items i
       inner join Packages p on (i.package_id = p.id and p.package_type = 'general')
    ) pg on (i.location = pg.location)
  left join 
    (select i.location, p.id
     from Items i
       inner join Packages p on (i.package_id = p.id and p.package_type = 'special')
    ) ps on (i.location = ps.location)

Giải pháp này về cơ bản lấy các vị trí và kết hợp nó vào gói với chung (được giả định là tồn tại; do đó inner join ) và gói đặc biệt (là tùy chọn; do đó left join ). Nó tạo ra các bản ghi như sau:

location | general-package | [special-package]

Sau đó, nó sử dụng MySQL IF hàm để tìm cách đầu tiên chọn ID của gói đặc biệt, sau đó quay trở lại ID của gói chung.

Giải pháp thứ 2 (thông qua ép kiểu enum thành số nguyên):

select i.location, p.id
from
  (select i.location, max(cast(package_type as unsigned)) as package_type
   from Items i
     left join Packages p on (i.package_id = p.id)
   group by location
  ) i
  inner join 
    (select i.location, p.id, p.package_type
     from Items i
       inner join Packages p on (i.package_id = p.id)
    ) p on (i.location = p.location and i.package_type = p.package_type)

Giải pháp này khai thác thực tế rằng enums được lưu trữ dưới dạng số nguyên. Nó chuyển enum thành một số nguyên. special trong trường hợp này sẽ trả về 2general sẽ trả về 1 . Vì giá trị đặc biệt này được đảm bảo cao hơn giá trị chung trong trường hợp này (tức là 2> 1), chúng tôi có thể sử dụng MAX chức năng tổng hợp. Bây giờ về cơ bản chúng ta có một bảng về các vị trí và "gói được đề xuất" của chúng (tức là đặc biệt nếu nó tồn tại, nói chung nếu không). Chúng tôi chỉ cần kết hợp điều này với truy vấn thông thường cùng với loại gói dự kiến ​​và nó trả về kết quả chính xác.

Tuyên bố từ chối trách nhiệm:Tôi không chắc về hiệu quả của một trong hai phương pháp này, vì vậy bạn có thể muốn tự mình kiểm tra điều này.

Nếu bạn đang muốn thiết kế lại bảng hoặc không chuẩn hóa nó cho hiệu quả, tôi nghĩ thiết kế này có thể phù hợp hơn:

GeneralPackages table
id, name
1, General Package 1

SpecialPackages table
id, name
1, Special Package 1
2, Special Package 2

Items table
id, general_package_id, special_package_id, location
1, 1, NULL, America
2, 1, 2, Europe

Ưu điểm là việc thực thi một số quy tắc ở cấp cơ sở dữ liệu sẽ dễ dàng hơn:

  • Một vị trí phải luôn có một gói chung (Items.general_package_id có thể được định nghĩa là KHÔNG ĐẦY ĐỦ)
  • Một vị trí chỉ được có một gói chung duy nhất (thêm nó vào một trường chứ không phải tham gia đảm bảo rằng chỉ có một gói được chỉ định)
  • Một vị trí có thể có nhiều nhất một gói đặc biệt (thêm nó vào một trường chứ không phải tham gia đảm bảo rằng chỉ có một gói được chỉ định)
  • Một khóa ngoại trên Items.general_package_id =GeneralPackages.id sẽ đảm bảo rằng cột đó chỉ chứa các gói hợp lệ "chung".
  • Điều tương tự cũng có thể được thực hiện đối với special_package_id.

Điều bất lợi là bạn có thể cần phải sử dụng UNION ALL mỗi khi bạn sử dụng một trong các truy vấn cũ của mình.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. DataTable với Ajax không hoạt động tốt sau khi sử dụng serverSide:true

  2. Hoàn thành Hướng dẫn xóa mềm &khôi phục bản ghi đã xóa của Laravel 8

  3. Cách cài đặt và cấu hình MySQL trên Ubuntu

  4. Cyrillic, AJAX và cơ sở dữ liệu

  5. mysql chọn tổng nhóm theo ngày