Chọn các hàng dựa trên ngày mới nhất có nhiều liên kết


8

Tôi có truy vấn này ( SQLFiddle ):

SELECT
c.name,
a.user_id,
a.status_id,
a.title,
a.rtime,
u.user_name,
s.status_name

FROM company c

LEFT JOIN action a ON a.company_id=c.id
LEFT JOIN user u ON u.id=a.user_id
LEFT JOIN status s ON s.id=a.status_id



WHERE u.user_name='Morgan'

-- WHERE c.name='Fiddle'

GROUP BY c.id

HAVING a.rtime IS NULL OR a.rtime = (
 SELECT max(rtime)
 FROM action a2
 WHERE deleted IS NULL
 AND a2.company_id = c.id
 )

Vấn đề 1

Tôi muốn liệt kê tất cả các công ty, và hiển thị cho người dùng và trạng thái nơi họ thực hiện hành động cuối cùng đối với công ty. Đồng thời cho thấy các công ty nơi không có hành động đã được thực hiện.

Vấn đề 2

Tôi cũng cần có khả năng tìm kiếm người dùng theo tên, do đó chọn tất cả các công ty là người dùng này có hoạt động cuối cùng. Truy vấn được tạo từ một biểu mẫu, vì vậy tôi có thể đưa ra các biến.


Hiện tại tôi không thể thay đổi cơ sở dữ liệu SCHema, nhưng lời khuyên cho việc di chuyển trong tương lai sẽ được đánh giá cao hơn nhiều.

Tôi đã thử ràng buộc nó cùng với INNER JOIN ( SELECT.. ) t ONnhưng tôi không thể quay đầu lại được.

Tôi cũng đã thử các phương pháp từ đây , đâyđây nhưng tôi không thể có được người có hoạt động mới nhất ngay.

Phiên bản MySQL: 5.5.16. Bảng công ty có khoảng 1 hàng máy và bảng hành động ở mức 70K, đang tăng lên. Hiệu suất là quan trọng đối với tôi ở đây.

Làm thế nào điều này có thể được giải quyết?


2
Xem câu hỏi này: Truy vấn tối ưu hóa MySQL Thay vì MAX(Marks)mỗi TaskID, bạn muốn MAX(ActivityDate)mỗi Company.) Không có nhiều khác biệt nếu bạn có một bảng hoặc tham gia.
ypercubeᵀᴹ

Câu trả lời:


7

Truy vấn của bạn có thể được đơn giản hóa để:

SELECT
    c.id,
    c.name,
    a.rtime,
    s.status_name,
    u.user_name
FROM company c
    LEFT JOIN
      ( SELECT 
            company_id,
            MAX(rtime) AS maxdate
        FROM action
        WHERE deleted IS NULL
        GROUP BY company_id
      ) AS x ON x.company_id = c.id
    LEFT JOIN action a ON  a.deleted IS NULL
                       AND a.company_id = x.company_id 
                       AND a.rtime = x.maxdate 
    LEFT JOIN user u ON u.id = a.user_id
    LEFT JOIN status s ON s.id = a.status_id
WHERE 
    c.name LIKE 'Company%' ;

Một chỉ mục trên (deleted, company_id, rtime)sẽ làm cho bảng phụ xuất phát hiệu quả. Tôi cho rằng bạn đã có các chỉ mục trên các cột được sử dụng cho các phép nối và trên Company (name).

Câu đố SQL


1
Điều này đơn giản hơn và dường như nhanh hơn khoảng 0,3 giây trên 100 hàng so với câu trả lời của tôi.
stiq

2

Sau khi thử các câu trả lời khác nhau, tôi đã làm cho nó hoạt động, nhưng tôi thấy nó chậm trong thiết lập của mình.

ypercube chỉ cho tôi một câu trả lời chỉ ra những câu hỏi tương tự khác về cách MySQL phân nhóm kết quả. Điều này dẫn tôi đến tài nguyên này , nơi cuối cùng tôi đã hiểu chuyện gì đang xảy ra.

Kết quả là một truy vấn như thế này:

SELECT
c.id,
c.name,

a.rtime,

s.status_name,

u.user_name


FROM company c

LEFT JOIN (
    SELECT 
        a.company_id,
        a.rtime,
        a.user_id,
        a.status_id
        FROM
            (
            SELECT company_id,
 MAX(rtime) as maxdate
            FROM action
            WHERE deleted IS NULL
            GROUP BY company_id
            ) as x

        LEFT JOIN action a ON a.rtime=x.maxdate AND a.company_id=x.company_id

) as a ON a.company_id=c.id

LEFT JOIN user u ON u.id=a.user_id
LEFT JOIN status s ON s.id=a.status_id

WHERE (1)

-- Search by user
-- AND u.user_name LIKE 'Johnny'

-- Seach by company name
AND c.name LIKE 'Company%'

Đây là một câu đố với truy vấn làm việc


1

Bạn cần di chuyển các bảng người dùng, hành động và trạng thái vào một truy vấn phụ, như thế này:

SELECT
c.name,
a.user_id,
a.status_id,
a.title,
a.max_rtime,
a.user_name,
a.status_name

FROM company c

LEFT JOIN
(select company_id, user_id, 
 max(rtime) max_rtime, 
 title, status_id, s.status_name,
 u.user_name
 from action INNER JOIN
  status s ON s.id=action.status_id
  INNER JOIN user u ON u.id=action.user_id
 where action.deleted IS NULL
 group by company_id, user_id, status_id, s.status_name, title, u.user_name
) a ON a.company_id=c.id AND a.user_name='Morgan'


GROUP BY c.id

Câu đố SQL

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.