【问题标题】:MySQL derived table with join带有连接的 MySQL 派生表
【发布时间】:2015-06-24 08:02:49
【问题描述】:

在以下查询中,我在返回 count2 的正确值时遇到了问题。

我需要的是从 table2 中获取行数,这可以通过使用派生表 t 轻松完成:

SELECT name, 
(SELECT COUNT(*) FROM `table1`) AS count1,
(SELECT COUNT(*) FROM (
    SELECT COUNT(*) FROM `table2` t2) WHERE t2.user = prf.user)
) t AS count2,
(SELECT SUM(a) FROM `table3`) AS count3
FROM `profiles` prf
WHERE 1=1
AND prf.user = 1

问题在于 WHERE t2.user = prf.user 语句失败,因为 prf 表超出了子查询的范围。

我怎样才能实现上述目标?

编辑:我正在添加实际查询,以防它有助于更​​好地掌握:

SELECT PRF.BranchID, PRF.user_id, CONCAT_WS(" ",PRF.lastname,PRF.firstname) Synergatis, 
( SELECT COUNT(*) FROM Actions A JOIN Requests R ON R.RequestID=A.RequestID WHERE A.ActionStatus = 302 AND A.UserOwner = PRF.user_id AND A.ActionDate BETWEEN '2015-06-01' AND '2015-06-10' ) AS energeies, 
( SELECT COUNT(DISTINCT RPP.RequestID) FROM VW_Xartofylakio_Synergati VV JOIN Requests_Prop RPP ON RPP.PropertyID = VV.PropertyID JOIN Requests R ON R.RequestID = RPP.RequestID WHERE VV.CurrUsr = PRF.user_id AND R.ModifyTime BETWEEN '2015-06-01' AND '2015-06-10' ) AS zitiseis_eidikes, 
( SELECT COUNT(DISTINCT(CustomerID)) FROM Demo_Orders_M WHERE DemoOrderStatus=253 AND USER=PRF.user_id AND DemoOrderDate BETWEEN '2015-06-01' AND '2015-06-10' ) AS endiaferomenoi, 
( SELECT COUNT(*) AS cnt FROM Demo_Orders_M DOM JOIN Actions A ON DOM.DemoOrderID = A.DemoOrderID WHERE DOM.User = PRF.user_id AND DOM.DemoOrderStatus = 253 AND A.ActionDate BETWEEN '2015-06-01 14:56:19' AND '2015-06-30 14:56:19' GROUP BY DOM.CustomerID, DOM.User HAVING COUNT(*) > 1 ) AS anakykl_endiaf, 
( SELECT COUNT(*) FROM Demo_Orders_M DOM WHERE DOM.`User`=PRF.user_id AND DemoOrderStatus = 253 AND DOM.DemoOrderDate BETWEEN '2015-06-01' AND '2015-06-10' ) AS epideixeis, 
( SELECT COUNT(DISTINCT(DOD.PropertyID)) AS PropertyID FROM Demo_Orders_M DOM JOIN Demo_Orders_D DOD ON DOM.DemoOrderID = DOD.DemoOrderID JOIN Actions A ON DOD.DemoOrderID = A.DemoOrderID WHERE DOM.DemoOrderStatus = 253 AND DOM.User = PRF.user_id AND A.ActionDate BETWEEN '2015-06-01' AND '2015-06-10' ) AS monadika_akinita
FROM tbl_profiles PRF 
WHERE 1=1 
AND PRF.user_id IN (
    SELECT a.user_id FROM tbl_profiles a WHERE a.user_id IN ('248','1159','486','183') 
    OR a.GroupID IN (SELECT b.GroupID FROM L_Groups b WHERE b.ManagerID IN ('248','1159','486','183')) 
    ) 
ORDER BY PRF.user_id

我所指的子查询是返回结果为 anakykl_endiaf 的子查询。

【问题讨论】:

  • 您能添加一些示例和您的预期结果吗?
  • 子查询返回 3 行,根据我的数据是正确的,但是我需要返回行数而不是行本身。我得到的错误是“状态 1242 - 子查询返回超过 1 行”。
  • 您对“WHERE 1=1”部分是认真的吗?
  • 此查询是报告系统的一部分,其中不授予任何条件,因为它们取决于用户用于创建报告的字段。因此,我使用 where 1=1 开始动态添加条件。
  • 您能否在 Demo_Orders_M 和说明问题的 Actions 上发布数据。根据子查询确实为 user_id 返回多行的数据,它看起来完全有可能(例如,如果 Demo_Orders_M 有多个行用于同一用户,但该用户具有不同的 customerID 值)

标签: mysql join derived-table


【解决方案1】:

我怀疑这不是因为prf 表,而是因为t2 表......在内部子查询中使用外部别名没有限制,因为有像相关子查询这样的东西。你的问题是你有相反的情况:你在外部查询中引用内部别名。

(SELECT COUNT(*) 
 FROM (SELECT COUNT(*) FROM `table2` t2) WHERE t2.user = prf.user)

你为什么在这里选择 count 两次?你可以改成这样:

(SELECT COUNT(*) 
 FROM (SELECT COUNT(*) FROM `table2` t2 WHERE t2.user = prf.user))

或者这个:

(SELECT COUNT(*) 
 FROM `table2` t2 WHERE t2.user = prf.user)

【讨论】:

  • 我选择 count 两次,因为我需要首先根据 HAVING count > 1 条件执行计数,然后计算符合此条件的行。实际查询要复杂得多,以上只是一个模型。
【解决方案2】:

一个尝试的建议。

您在 SELECT 中有子查询,在这种情况下,它们必须各自只返回一行。出于某种原因(如果没有测试数据,我们无法真正判断)其中之一返回超过 1 行,因此失败。

作为临时步骤,将查询更改为加入子查询,这样在存在重复项时应该会更加明显(并且可能效率更高,具体取决于数据)。

类似这样的东西(没有测试所以可能有一些错别字):-

SELECT PRF.BranchID, 
    PRF.user_id, 
    CONCAT_WS(" ",PRF.lastname,PRF.firstname) Synergatis, 
    ar.energeies,
    vrr.zitiseis_eidikes,
    m.endiaferomenoi, 
    ae.anakykl_endiaf,
    d.epideixeis,
    ddd.monadika_akinita
FROM tbl_profiles PRF 
LEFT OUTER JOIN
( 
    SELECT A.UserOwner AS DomUser, COUNT(*) AS energeies
    FROM Actions A 
    JOIN Requests R ON R.RequestID=A.RequestID 
    WHERE A.ActionStatus = 302 
    AND A.ActionDate BETWEEN '2015-06-01' AND '2015-06-10' 
    GROUP BY A.UserOwner
) ar 
ON ar.DomUser = PRF.user_id 
LEFT OUTER JOIN
( 
    SELECT VV.CurrUsr AS DomUser, COUNT(DISTINCT RPP.RequestID) AS zitiseis_eidikes
    FROM VW_Xartofylakio_Synergati VV 
    JOIN Requests_Prop RPP ON RPP.PropertyID = VV.PropertyID 
    JOIN Requests R ON R.RequestID = RPP.RequestID 
    WHERE R.ModifyTime BETWEEN '2015-06-01' AND '2015-06-10' 
    GROUP BY VV.DomUser
) vrr 
ON vrr.DomUser = PRF.user_id 
LEFT OUTER JOIN
( 
    SELECT `USER` AS DomUser, COUNT(DISTINCT(CustomerID)) AS endiaferomenoi
    FROM Demo_Orders_M 
    WHERE DemoOrderStatus=253 
    AND DemoOrderDate BETWEEN '2015-06-01' AND '2015-06-10' 
    GROUP BY DomUser
) m
ON PRF.user_id  = m.DomUser
LEFT OUTER JOIN
( 
    SELECT DOM.CustomerID, DOM.`User` AS DomUser, COUNT(*) AS anakykl_endiaf 
    FROM Demo_Orders_M DOM 
    JOIN Actions A ON DOM.DemoOrderID = A.DemoOrderID 
    WHERE DOM.DemoOrderStatus = 253 
    AND A.ActionDate BETWEEN '2015-06-01 14:56:19' AND '2015-06-30 14:56:19' 
    GROUP BY DOM.CustomerID, DOM.DomUser 
    HAVING COUNT(*) > 1 
) ae
ON PRF.user_id  = ae.DomUser
LEFT OUTER JOIN
( 
    SELECT DOM.`User` AS DomUser, COUNT(*) AS epideixeis
    FROM Demo_Orders_M DOM 
    WHERE DemoOrderStatus = 253 
    AND DOM.DemoOrderDate BETWEEN '2015-06-01' AND '2015-06-10' 
    GROUP BY DOM.DomUser 
) d 

编辑

如果您只想计算 anakykl_endiaf 字段中用户的 customerID 字段数,请将其更改为计算不同的 customerID。即,对于上述查询,我​​已将其更改为:-

LEFT OUTER JOIN
( 
    SELECT DOM.`User` AS DomUser, COUNT(DISTINCT DOM.CustomerID) AS anakykl_endiaf 
    FROM Demo_Orders_M DOM 
    JOIN Actions A ON DOM.DemoOrderID = A.DemoOrderID 
    WHERE DOM.DemoOrderStatus = 253 
    AND A.ActionDate BETWEEN '2015-06-01 14:56:19' AND '2015-06-30 14:56:19' 
    GROUP BY DOM.DomUser 
    HAVING COUNT(*) > 1 
) ae

【讨论】:

  • @GiorgiNakeuri - 他正在使用 GROUP BY 子句选择计数,但 GROUP BY 子句指定了 2 个字段,而在子查询中只检查了一个字段是否匹配。因此,如果在 Demo_Orders_M 表上,用户有 2 条记录,每条记录都有不同的 CustomerID 字段,则子查询将为该用户返回 2 个计数,因此查询将失败。
猜你喜欢
  • 2014-12-28
  • 2016-09-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2016-01-05
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
相关资源
最近更新 更多