Subquery không thể tìm thấy cột từ tham gia của superquery


7

Tôi đang gặp một số rắc rối với SQL: Về cơ bản, tôi đang cố gắng lấy lại kết quả có chứa một tổng số TẤT CẢ các câu hỏi cho nhân viên (được nhóm theo công ty) và cũng thêm "onetime_items" được thêm thủ công vào các mục trong một bảng khác nhau.

Tôi hiện có câu lệnh SQL này (Tôi đang sử dụng MySQL):

SELECT 
CONCAT_WS(
    ', ', count(DISTINCT CONCAT(emailaddress, '_', e.id)),
    (
        SELECT GROUP_CONCAT(items SEPARATOR '; ') as OneTimeItems
        FROM ( 
            SELECT CONCAT_WS(
                ': ', oi.item_name, SUM(oi.item_amount)
            ) items 
            FROM onetime_item oi 
            WHERE oi.company_id = e.company_id
            AND oi.date BETWEEN '2015-12-01'
            AND LAST_DAY('2015-12-01') 
            GROUP BY oi.item_name 
        ) resulta
    )
) as AllItems,
e.id,
LEFT(e.firstname, 1) as voorletter,
e.lastname
FROM question q 
LEFT JOIN employee e ON q.employee_id = e.id 
WHERE 1=1 
AND YEAR(created_at) = '2015'
AND MONTH(created_at) = '12' 
GROUP BY e.company_id

Bây giờ tôi nhận được lỗi sau:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'e.company_id' in where clause

Ngày được sử dụng là ngày giả và mệnh đề 1 = 1 ở dưới cùng bởi vì tôi đang tạo câu lệnh where dựa trên các giá trị đầu vào của người dùng.

Tất cả các cột DO tồn tại trong nhân viên bảng và tham gia bên trái hoạt động (Tôi đã thử nhập id theo cách thủ công thay vì sử dụng tham chiếu cột và nó hoạt động, tôi đã nhận được kết quả đúng)

Tôi cũng xin lỗi nhưng tôi không được phép đăng một lược đồ bảng hoặc bất cứ điều gì liên quan đến cấu trúc DB trực tuyến.

Bất kỳ ý tưởng nào về lý do tại sao tham chiếu đến e.company_id không thành công?

EDIT: Đây là bộ kết quả tôi cần:

5, Het is je verjaardag: 1; Skivakantie: 1; Telefonische leadvergoeding: 8

Việc xây dựng như sau: 5 = dấu phẩy được phân tách để lấy phần còn lại. Dẫn là sự kết hợp độc đáo từ bảng Câu hỏi và phần còn lại của kết quả được tạo từ onetime_items.

EDIT 2 : SQL fiddle liên tục gây ra lỗi cho tôi vì vậy tôi sẽ đăng một DB nhỏ đã tạo ra với một ít dữ liệu đã tạo: http://pastebin.com/cCveVtGr


2
Có lẽ bởi vì nó được lồng quá sâu
Philᵀᴹ 15/1/2016

@Phil Bất cứ ý tưởng làm thế nào để có được tài liệu tham khảo làm việc?
FMashiro

GROUP BYhoạt động "sau" chọn (đơn giản hóa rất nhiều), vì vậy đôi khi nó không thấy các cột bạn không chọn (có thể phụ thuộc vào tối ưu hóa trình lập kế hoạch thực hiện cho truy vấn của bạn, v.v.). Vì vậy, thêm , e.company_idsau e.lastname.
jkavalik

@jkavalik Tôi đã thử thêm nó vào SQL và chạy nó nhưng nó vẫn báo lỗi "# 1054 - Cột không xác định 'e.company_id' trong 'mệnh đề where'"
FMashiro

@FMashiro ah, xin lỗi, tôi đã bị phân tâm bởi một lỗi khác mà tôi đã từng mắc phải ..
jkavalik

Câu trả lời:


4

Nguyên nhân của vấn đề được xác định bởi @Phil trong các bình luận :

Có lẽ bởi vì nó được lồng quá sâu

Bạn có 2 lớp lồng nhau và tham chiếu của bảng ekhông thể "nhìn thấy" thông qua 2 lớp này trong MySQL.

Truy vấn nội tuyến tương quan thường có thể được chuyển đổi thành các bảng dẫn xuất và sau đó được LEFTnối với các bảng khác trong FROMmệnh đề nhưng chúng phải được chuyển thành không tương thích (trong MySQL. Trong các DBMS khác, bạn có thể sử dụng phép LATERALnối hoặc tương tự OUTER APPLY.

Viết lại đầu tiên để hoàn thành công việc:

SELECT 
    CONCAT_WS(
        ', ', count(DISTINCT CONCAT(q.emailaddress, '_', e.id)),
        dv.OneTimeItems
    ) as AllItems,
    e.id,
    LEFT(e.firstname, 1) as voorletter,
    e.lastname
FROM question q 
LEFT JOIN employee e ON q.employee_id = e.id 
LEFT JOIN
    (
        SELECT company_id,
               GROUP_CONCAT(items SEPARATOR '; ') AS OneTimeItems
        FROM ( 
            SELECT oi.company_id,
                   CONCAT_WS(
                ': ', oi.item_name, SUM(oi.item_amount)
            ) items 
            FROM onetime_item oi 
            WHERE oi.date BETWEEN '2015-12-01'
                              AND LAST_DAY('2015-12-01') 
            GROUP BY oi.company_id, oi.item_name 
        ) resulta
        GROUP BY company_id
    ) AS dv
    ON dv.company_id = e.company_id
WHERE 1=1 
AND YEAR(q.created_at) = '2015'
AND MONTH(q.created_at) = '12' 
GROUP BY e.company_id ;

Kiểm tra trong SQLfiddle .


Không liên quan đến các ý kiến ​​vấn đề:

  • GROUP BY e.company_idtrong khi selectdanh sách có e.id, LEFT(e.firstname, 1), e.lastname. Tất cả những điều này sẽ mang lại kết quả tùy ý từ một nhân viên (ít nhiều ngẫu nhiên) cho mỗi công ty - hoặc thậm chí trong những trường hợp cực kỳ hiếm gặp kết quả tùy ý từ 2 hoặc 3 nhân viên khác nhau! MySQL cho phép (trước 5.7) việc sử dụng nhóm xấu như vậy có thể gây ra kết quả sai. Nó đã được sửa trong 5.7 và các cài đặt mặc định sẽ từ chối truy vấn này.
  • Điều kiện:

    YEAR(created_at) = '2015' AND MONTH(created_at) = '12'

    không thể sử dụng các chỉ mục. Nó tốt hơn để viết lại với một trong hai BETWEENnếu cột là các DATEloại với một điều kiện phạm vi bao gồm độc quyền, mà hoạt động hoàn hảo với bất kỳ loại datetime ( DATE, DATETIME, TIMESTAMP) của bất kỳ chính xác:

    -- use only when the type is DATE only
    date BETWEEN '2015-12-01' AND LAST_DAY('2015-12-01')
    

    hoặc là:

    -- use when the type is DATE, DATETIME or TIMESTAMP
    created_at >= '2015-12-01' AND created_at < '2016-01-01'     
    

Điều này không hoạt động vì company_id được định dạng lại thành OneTimeItems trong dv nên bạn không thể sử dụng nó trong "mệnh đề BẬT" thấy lỗi: # 1054 - Cột không xác định 'dv.company_id' trong 'trên mệnh đề'
FMashiro

@FMashiro Bạn có oi.datetrong truy vấn nhưng pastebin không có datetrong bảng đó.
ypercubeᵀᴹ

Đã cập nhật pastebin trong chuỗi và đây là liên kết một lần nữa, xin lỗi vì không bao gồm pastebin.com/cCveVtGr
FMashiro
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.