2008-10-15 34 views
53

Trong MySQL 5.0 tại sao lỗi sau xảy ra khi cố tạo chế độ xem với truy vấn phụ trong mệnh đề FROM?MySQL: Xem với Truy vấn phụ trong Giới hạn khoản TỪ

ERROR 1349 (HY000): Xem lý lịch thành CHỌN chứa một subquery trong mệnh đề FROM

Nếu đây là một hạn chế của động cơ MySQL, thì tại sao không họ thực hiện tính năng này chưa?

Ngoài ra, một số cách giải quyết tốt cho giới hạn này là gì?

Có cách giải quyết nào phù hợp với bất kỳ truy vấn con nào trong mệnh đề FROM hay không có một số truy vấn không thể diễn tả mà không sử dụng truy vấn phụ trong mệnh đề FROM?


Một truy vấn ví dụ (được chôn cất trong một chú thích):

SELECT temp.UserName 
FROM (SELECT u1.name as UserName, COUNT(m1.UserFromId) as SentCount 
     FROM Message m1, User u1 
     WHERE u1.uid = m1.UserFromId 
     Group BY u1.name HAVING SentCount > 3) as temp 
+0

Cảm ơn bạn đã đăng bài này. Tôi thường tránh các khung nhìn trong mysql. Làm việc trên một trường hợp cạnh, cố gắng để hội fk bảng - shoehorning chúng vào một cái nhìn. Bây giờ điều này. Thật là một nỗi đau - tất cả những hạn chế này trên truy vấn phụ? Sẵn sàng chuyển sang một động cơ khác. – eggmatters

Trả lời

17

Không thể truy vấn trong bình luận của bạn chỉ được viết như:

SELECT u1.name as UserName from Message m1, User u1 
    WHERE u1.uid = m1.UserFromID GROUP BY u1.name HAVING count(m1.UserFromId)>3 

Đó cũng nên giúp đỡ với vấn đề tốc độ được biết đến với các truy vấn con trong MySQL

+0

Cảm ơn, tôi đã không nhận ra bạn có thể làm GROUP BY mà không có chức năng tổng hợp trong SELECT. Vì vậy, một trong những lý do họ không cho phép truy vấn con trong mệnh đề FROM trong MySQL là do vấn đề tốc độ? – Daniel

+0

Nó không nhất thiết vì tốc độ trong trường hợp cụ thể này. Vì nó là ngay bây giờ, trình tối ưu hóa không hoạt động tốt trên các truy vấn phụ cả. Tránh xa họ nếu có thể. Điều này đang được cố định trong 6.0 và rất nhiều tiến bộ đã được thực hiện trên nó, nhưng đó là trong 6.0 và bạn đang sử dụng 5.0. –

+1

Vui lòng không sử dụng cú pháp ngầm. Nó là một mẫu đối tượng SQL và được trả về bằng một cú pháp tốt hơn 20 năm trước. – HLGEM

5

Nó dường như là một vấn đề được biết đến.

http://dev.mysql.com/doc/refman/5.1/en/unnamed-views.html

http://bugs.mysql.com/bug.php?id=16757

Nhiều TRÊN truy vấn có thể được viết lại như (trái bên ngoài) tham gia và IS (KHÔNG) NULL của một số loại. ví dụ

SELECT * FROM FOO WHERE ID IN (SELECT ID FROM FOO2) 

có thể được viết lại như

SELECT FOO.* FROM FOO JOIN FOO2 ON FOO.ID=FOO2.ID 

hoặc

SELECT * FROM FOO WHERE ID NOT IN (SELECT ID FROM FOO2) 

có thể

SELECT FOO.* FROM FOO 
LEFT OUTER JOIN FOO2 
ON FOO.ID=FOO2.ID WHERE FOO.ID IS NULL 
+0

Nhưng làm cách nào bạn viết lại một truy vấn trong mệnh đề FROM? Ví dụ, làm thế nào tôi có thể viết lại truy vấn này ?: CHỌN temp.UserName TỪ ( CHỌN u1.name như UserName, COUNT (m1.UserFromId) như SentCount TỪ nhắn m1, User u1 ĐÂU u1.uid = m1. UserFromId Nhóm BY u1.name HAVING SentCount> 3 ) như temp – Daniel

+0

Tôi không nghĩ là bạn có thể, nhưng bạn có thể tạo một khung nhìn thứ hai và chọn từ đó thay vì sử dụng sub-select, theo như tôi biết. Nếu bạn không quan tâm đến một proc được lưu trữ, bạn cũng có thể sử dụng các bảng tạm thời (giả sử phiên bản MySQL đủ gần đây). – Nikki9696

+0

Hoặc, như tôi đã nhận thấy, giải pháp của Grant có thể phù hợp với bạn. – Nikki9696

74

tôi đã cùng một vấn đề. Tôi muốn tạo ra một cái nhìn để hiển thị thông tin của năm gần nhất, từ một bảng với các hồ sơ từ năm 2009 đến 2011. Đây là truy vấn ban đầu:

SELECT a.* 
FROM a 
JOIN ( 
    SELECT a.alias, MAX(a.year) as max_year 
    FROM a 
    GROUP BY a.alias 
) b 
ON a.alias=b.alias and a.year=b.max_year 

Outline của giải pháp:

  1. tạo một cái nhìn cho mỗi subquery
  2. thay subqueries với những quan điểm

Dưới đây là các truy vấn giải pháp:

CREATE VIEW v_max_year AS 
    SELECT alias, MAX(year) as max_year 
    FROM a 
    GROUP BY a.alias; 

CREATE VIEW v_latest_info AS 
    SELECT a.* 
    FROM a 
    JOIN v_max_year b 
    ON a.alias=b.alias and a.year=b.max_year; 

Nó hoạt động tốt trên mysql 5.0.45, không có nhiều hình phạt tốc độ (so với thực hiện truy vấn phụ gốc mà không có bất kỳ chế độ xem nào).

+4

không sao lưu, như mysql khôi phục quan điểm dựa trên tên của họ vì vậy nó sẽ cố gắng khôi phục "v_latest_info" đầu tiên và sẽ thất bại vì "v_max_year" chưa tồn tại ... – Apolo

+0

Sẽ tạo ra nhiều khung nhìn này dẫn đến các vấn đề về hiệu suất ? – Annie

+0

Điều này phải được đánh dấu là câu trả lời. – enchance

3

tạo chế độ xem cho mỗi truy vấn con là cách để thực hiện. Có nó làm việc như một say mê.

4

Bạn có thể giải quyết vấn đề này bằng cách tạo một VIEW riêng cho bất kỳ truy vấn con nào bạn muốn sử dụng và sau đó tham gia vào đó trong VIEW bạn đang tạo. Dưới đây là ví dụ: http://blog.gruffdavies.com/2015/01/25/a-neat-mysql-hack-to-create-a-view-with-subquery-in-the-from-clause/

Điều này khá thuận tiện vì bạn sẽ rất muốn sử dụng lại nó và giúp bạn giữ DRY SQL của mình.

+0

Hi Ninjabber - hãy chia sẻ bất kỳ khung nhìn cụ thể nào bạn đã trải nghiệm. Các khung nhìn rất mạnh mẽ trong MySQL, nhưng có, bạn cần phải biết các ins and outs của chúng để bảo vệ chống lại các vấn đề về hiệu suất, nhưng theo kinh nghiệm của tôi thì chúng dễ dàng tránh được. – Gruff

+1

không có trong mysql 5.0 Tôi sợ. Không có phiên bản 5.0 nhưng tự tạo một phiên bản, đặt 3 truy vấn con trong chế độ xem và tham gia chúng trên các cột được lập chỉ mục. Bạn sẽ ngạc nhiên bởi kế hoạch giải thích. Với các truy vấn con thực sự tinh vi mà cá nhân làm việc tốt, tôi đã gặp vấn đề ngay cả trong 5.6. 5.7 là khác nhau. Có việc xử lý nhiều hơn oracle-ish – ninjabber

+1

quên thêm: Nâng cấp máy của bạn lên 5.7 và không có giới hạn nào. Ngay cả AWS cũng đã thông báo sự hỗ trợ của 5.7 trên RDS Lý do duy nhất bạn có thể không muốn nâng cấp là nếu bạn sử dụng một số máy chủ ứng dụng (nói Hybris) chưa hỗ trợ 5.7. Nhưng đó là một vấn đề thời gian kể từ 5.7 chỉ là ở một mức độ khác nhau và đến nay là động cơ MySQL tốt nhất từng có. Điều quan trọng nhất là cuối cùng chúng ta có thể sử dụng nhiều hơn một lõi và xử lý các giao dịch song song để cho phép bạn chơi với bộ nhớ đệm và cuối cùng sử dụng lợi ích của nó – ninjabber

Các vấn đề liên quan