子子查询无法在父选择中找到连接列

时间:2016-01-14 12:45:15

标签: mysql join subquery

我遇到了一些SQL问题: 基本上我试图获得一个结果集,其中包含向员工提出的所有问题的总和(按公司分组),并且还添加" onetime_items"这是在另一个表中手动添加的项目。

我目前有这个SQL语句(我使用MySQL):

SELECT 
CONCAT_WS(
    ', ', count(DISTINCT CONCAT(emailaddress, '_', a.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

现在我收到以下错误:

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'e.company_id' in 'where clause'

使用的日期是虚拟日期。

此列已存在于表employee中且左连接有效(我尝试手动输入id而不是使用列引用并且它工作正常,我得到了正确的结果)

为什么对e.company_id的引用失败了?

1 个答案:

答案 0 :(得分:0)

感谢dba.stackexchange.com

link:https://dba.stackexchange.com/questions/126339/subquery-cant-find-column-from-superquerys-join

通过ypersillycubeᵀᴹ

回答

这里是那里发布的答案,希望其他人也能从中获益! @Phil in the comments确定了问题的原因:在评论中: 可能是因为它的嵌套太深了 你有2层嵌套,表e的引用不能"参见"通过MySQL中的这两层。

相关内联子查询通常可以转换为派生表,然后LEFT连接到FROM子句中的其他表,但它们必须变为不相关(在MySQL中。在其他DBMS中,您可以使用LATERAL连接或类似外面申请。

完成工作的第一次重写:

  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 ;

SQLfiddle 中进行测试。

与问题评论无关:

有GROUP BY e.company_id,而选择列表有e.id,LEFT(e.firstname, 1), e.lastname。所有这些都会给每个公司的(或多或少随机的)员工带来任意结果 - 甚至在极少数情况下,来自2或3个不同员工的任意结果! MySQL允许(在5.7之前)对组的错误使用可能导致错误的结果。它已在5.7中修复,默认设置将拒绝此查询。 条件:

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

无法使用索引。如果列的DATE类型具有包含 - 排他范围条件,则可以使用BETWEEN进行重写,这对于任何精度的任何日期时间类型(DATE,DATETIME,TIMESTAMP)都可以完美地工作:

- 仅在类型为DATE时使用

date BETWEEN '2015-12-01' AND LAST_DAY('2015-12-01')

或:

- 当类型为DATE,DATETIME或TIMESTAMP

时使用
created_at >= '2015-12-01' AND created_at < '2016-01-01'