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

Trả lại xếp hạng từ nhiều bảng với mySQL

Tôi đề nghị chúng ta xây dựng truy vấn tăng dần, từng bước. Xác minh rằng kết quả truy vấn như chúng tôi mong đợi ở mỗi bước. Khi một cái gì đó "không hoạt động", hãy sao lưu một bước.

Chúng tôi muốn trả về ba hàng, mỗi hàng một trong ___Segmentations , cho một hotelid cụ thể

 SELECT r.seg_id
      , r.seg_text
   FROM ___Segmentations r
  WHERE r.seg_hotelid = :hotel_id
  ORDER BY r.seg_id

Thêm liên kết bên ngoài vào __Bookings

 SELECT r.seg_id
      , r.seg_text
      , b.boo_id
   FROM ___Segmentations r
   LEFT
   JOIN ___Bookings b
     ON b.boo_segmentation = r.seg_id
  WHERE r.seg_hotelid = :hotel_id
  ORDER
     BY r.seg_id
      , b.boo_id

Thêm liên kết bên ngoài vào ___BillableDatas

 SELECT r.seg_id
      , r.seg_text
      , b.boo_id
      , d.bil_id
   FROM ___Segmentations r
   LEFT
   JOIN ___Bookings b
     ON b.boo_segmentation = r.seg_id
   LEFT
   JOIN `___BillableDatas` d
     ON d.bil_bookingid = b.boo_id
  WHERE r.seg_hotelid = :hotel_id
  ORDER
     BY r.seg_id
      , b.boo_id
      , d.bil_id

Nếu đó là những hàng mà chúng tôi quan tâm, chúng tôi có thể làm việc trên việc tổng hợp.

 SELECT r.seg_id
      , r.seg_text
      , COUNT(DISTINCT b.boo_id) AS cnt_bookings
      , COUNT(DISTINCT d.bil_id) AS cnt_billable
   FROM ___Segmentations r
   LEFT
   JOIN ___Bookings b
     ON b.boo_segmentation = r.seg_id
   LEFT
   JOIN `___BillableDatas` d
     ON d.bil_bookingid = b.boo_id
  WHERE r.seg_hotelid = :hotel_id
  GROUP
     BY r.seg_id
      , r.seg_text
  ORDER
     BY r.seg_text

Bây giờ để có được tổng hợp với "tổng số".

Cách tiếp cận mà tôi sẽ thực hiện là tạo "bản sao" của các hàng, sử dụng thao tác CROSS JOIN. Chúng ta có thể thực hiện việc nối các hàng được trả về bởi truy vấn đầu tiên mà chúng ta đã viết, được tham chiếu dưới dạng một dạng xem nội tuyến. (Bí danh là q bên dưới.)

Nếu chúng ta có một tập hợp các hàng hoàn chỉnh, được lặp lại cho mỗi seg_id/seg_text (truy vấn đầu tiên mà chúng tôi đã viết), chúng tôi có thể sử dụng kết hợp có điều kiện.

Truy vấn cuối cùng mà chúng tôi đã viết (ngay ở trên) là một dạng xem nội tuyến trong truy vấn bên dưới, có bí danh là c .

SUM trong số cnt_bookings từ tất cả các hàng là tổng số.

Đối với các số lượng riêng lẻ, chúng tôi chỉ có thể bao gồm các hàng có seg_id phù hợp , tổng số của tập hợp con đó.

 SELECT q.seg_id
      , q.seg_text
      , SUM(IF(c.seg_id=q.seg_id,c.cnt_bookings,0))  AS cnt_bookings
      , SUM(c.cnt_bookings)                          AS tot_bookings
      , SUM(IF(c.seg_id=q.seg_id,c.cnt_billable,0))  AS cnt_billable
      , SUM(c.cnt_billable)                          AS tot_billable
   FROM ( SELECT t.seg_id
               , t.seg_text
            FROM ___Segmentations t
           WHERE t.seg_hotelid = :hotel_id_1
           ORDER BY t.seg_id
        ) q
  CROSS
   JOIN ( SELECT r.seg_id
               , COUNT(DISTINCT b.boo_id) AS cnt_bookings
               , COUNT(DISTINCT d.bil_id) AS cnt_billable
            FROM ___Segmentations r
            LEFT
            JOIN ___Bookings b
              ON b.boo_segmentation = r.seg_id
            LEFT
            JOIN `___BillableDatas` d
              ON d.bil_bookingid = b.boo_id
           WHERE r.seg_hotelid = :hotel_id
           GROUP
              BY r.seg_id
        ) c
  GROUP
     BY q.seg_id
      , q.seg_text
  ORDER
     BY q.seg_text

Trong SELECT danh sách, chúng ta có thể thực hiện phép chia để lấy phần trăm:cnt_bookings * 100.0 / tot_bookings

ví dụ:

 SELECT q.seg_id
      , q.seg_text

      , SUM(IF(c.seg_id=q.seg_id,c.cnt_bookings,0))  AS cnt_bookings
      , SUM(c.cnt_bookings)                          AS tot_bookings
      , SUM(IF(c.seg_id=q.seg_id,c.cnt_bookings,0))
        * 100.0 / SUM(c.cnt_bookings)                AS pct_bookings

      , SUM(IF(c.seg_id=q.seg_id,c.cnt_billable,0))  AS cnt_billable
      , SUM(c.cnt_billable)                          AS tot_billable
      , SUM(IF(c.seg_id=q.seg_id,c.cnt_billable,0))
        * 100.0 / SUM(c.cnt_billable)                AS pct_billable

Sửa đổi mệnh đề ORDER BY để trả về các hàng theo thứ tự bạn muốn

Xóa khỏi SELECT liệt kê các biểu thức trả về tot_bookingstot_billable .

CHỈNH SỬA

Tôi nghĩ rằng tôi đã bỏ lỡ tiêu chí ngày. Chúng ta có thể biến các phép nối bên ngoài thành các phép nối bên trong và thay thế CROSS JOIN bằng LEFT JOIN. Chúng tôi có khả năng trả về giá trị NULL cho cnt_bookingscnt_billable , chúng ta có thể bọc chúng trong hàm IFNULL () hoặc COALESCE () để thay thế NULL bằng không.

 SELECT q.seg_id
      , q.seg_text

      , SUM(IF(c.seg_id=q.seg_id,c.cnt_bookings,0))  AS cnt_bookings
      , SUM(c.cnt_bookings)                          AS tot_bookings
      , SUM(IF(c.seg_id=q.seg_id,c.cnt_bookings,0))
        * 100.0 / SUM(c.cnt_bookings)                AS pct_bookings

      , SUM(IF(c.seg_id=q.seg_id,c.cnt_billable,0))  AS cnt_billable
      , SUM(c.cnt_billable)                          AS tot_billable
      , SUM(IF(c.seg_id=q.seg_id,c.cnt_billable,0))
        * 100.0 / SUM(c.cnt_billable)                AS pct_billable

   FROM ( SELECT t.seg_id
               , t.seg_text
            FROM ___Segmentations t
           WHERE t.seg_hotelid = :hotel_id_1
           ORDER BY t.seg_id
        ) q
   LEFT
   JOIN ( SELECT r.seg_id
               , COUNT(DISTINCT b.boo_id) AS cnt_bookings
               , COUNT(DISTINCT d.bil_id) AS cnt_billable
            FROM ___Segmentations r
            JOIN ___Bookings b
              ON b.boo_segmentation = r.seg_id
            JOIN `___BillableDatas` d
              ON d.bil_bookingid = b.boo_id
             AND d.bil_date BETWEEN '2017-02-21' AND '2017-02-28'
           WHERE r.seg_hotelid = :hotel_id
           GROUP
              BY r.seg_id
        ) c
     ON 1=1   
  GROUP
     BY q.seg_id
      , q.seg_text
  ORDER
     BY q.seg_text


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để thực hiện time_to_minute trong Mysql?

  2. Tìm các hàng có giá trị cột trùng lặp / tương tự MySQL

  3. Hàm MySQL CRC32 () - Ví dụ

  4. kết nối cơ sở dữ liệu không thành công sau khi tạo tệp jar

  5. Làm cách nào để loại bỏ khoảng trắng đầu và cuối trong trường MySQL?