【问题标题】:How to reference field in a JOIN within a JOIN?如何在 JOIN 中引用 JOIN 中的字段?
【发布时间】:2017-10-18 18:55:22
【问题描述】:

在 JOIN 语句中选择子查询中的特定字段时,您使用点表示法来引用 table.field_name,但是,当在第一个 JOIN 中使用另一个子查询 JOIN 时该怎么办?

我的 JOIN w/in JOIN 示例:

JOIN (SELECT 
BUDGET.protocol_id, BUDGET.completed_date,
CONTRACT.completed_date,
REQUEST.completed_date,
RECEIVE.completed_date,
PC.completed_date,
FC.completed_date,
MGR.completed_date

FROM (SELECT completed_date, task_list_id, protocol_id FROM task WHERE task_name LIKE 'Budget%') BUDGET 

JOIN (SELECT completed_date, task_list_id, protocol_id FROM task WHERE task_name LIKE 'Contract%') CONTRACT 
    ON BUDGET.protocol_id = CONTRACT.protocol_id
    AND BUDGET.task_list_id = CONTRACT.task_list_id

JOIN (SELECT completed_date, task_list_id, protocol_id FROM task WHERE task_name LIKE 'Request%') REQUEST 
    ON BUDGET.protocol_id = REQUEST.protocol_id
    AND BUDGET.task_list_id = REQUEST.task_list_id

JOIN (SELECT completed_date, task_list_id, protocol_id FROM task WHERE task_name LIKE 'Protocol%') PC 
    ON BUDGET.protocol_id = PC.protocol_id
    AND BUDGET.task_list_id = PC.task_list_id

JOIN (SELECT completed_date, task_list_id, protocol_id FROM task WHERE task_name LIKE 'Financials%') FC 
    ON BUDGET.protocol_id = FC.protocol_id
    AND BUDGET.task_list_id = FC.task_list_id

JOIN (SELECT completed_date, task_list_id, protocol_id FROM task WHERE task_name LIKE 'Manager%') MGR 
    ON BUDGET.protocol_id = MGR.protocol_id
    AND BUDGET.task_list_id = MGR.task_list_id  

JOIN (SELECT completed_date, task_list_id, protocol_id FROM task WHERE task_name LIKE 'Receive%') RECEIVE
    ON BUDGET.protocol_id = RECEIVE.protocol_id
    AND BUDGET.task_list_id = RECEIVE.task_list_id
) TASK ON PCL.protocol_id = TASK.BUDGET.protocol_id

我一直在尝试对子查询做的是选择特定任务的完成日期,因此在 SELECT 语句中,我的直觉是对每个任务使用 TASK.BUDGET.completed_date。然而,我得到一个 ORA-00918: column ambiguously defined,所以使用 completed_date 的所有内容似乎都有问题

【问题讨论】:

  • 如果您运行您发布的所有代码(减去开头的JOIN (),它会运行吗?对我来说看起来不错,所以我猜你的错误是在外部选择或分组上。
  • 子查询它自己肯定会运行,尽管速度很慢。问题出现在我添加的主查询 SELECT 语句中:'TASK.BUDGET.completed_date, TASK.CONTRACT.completed_date, TASK.REQUEST.completed_date, TASK.RECEIVE.completed_date, TASK.PC.completed_date, TASK.FC.completed_date , TASK.MGR.completed_date' 抛出 00918 错误
  • ) TASK ON PCL.protocol_id = TASK.BUDGET.protocol_id -- 指向那个的左括号在哪里?每个子查询最好被认为是它自己的表......其中的所有内容都是自包含的,不能引用它之外的任何对象。 task.budget.completed_date 永远不会是正确的引用。编辑:如果您没有该任务参考,这可行,不是吗?您将要为每个子查询中的列加上别名以避免混淆(SELECT completed_date as budget_completed_date)或类似的东西
  • 正确的别名应该只是TASK.completed_date...BUDGET 的内部别名不会传递给外部查询。只有子查询/派生表别名将 (TASK)。
  • 类似地,为每个 completed_date 列赋予自己的别名。即.. CONTRACT.completed_date AS ContractCompletedDate 然后从外部查询中的列名中选择它们。即..TASK.ContractCompletedDate

标签: sql join inner-join


【解决方案1】:

使用条件聚合:

SELECT t.protocol_id,
       MAX(CASE WHEN task_name LIKE 'Budget%' THEN completed_date END) as budget_completed_date,
         . . . 
FROM task t
GROUP BY protocol_id;

我不太确定 task_list_id 是如何适应的。您可能还想以此进行汇总。

【讨论】:

  • 谢谢@Gordon Linoff。我是新手,所以我不熟悉条件聚合。你有什么参考资料可以让我学到更多吗?我想我会使用 Aliasing 快速修复,即使它速度较慢,然后了解有关条件聚合的更多信息以进行优化
  • @Dan 。 . .这似乎是您的代码的主要简化,一个聚合查询而不是大量的连接。
  • 你是对的,这在放入更大的查询时效果更好。谢谢。
【解决方案2】:

有点理解,但我想我明白了。

SELECT 
BUDGET.protocol_id, 
BUDGET.completed_date,
CONTRACT.completed_date,
REQUEST.completed_date,
RECEIVE.completed_date,
PC.completed_date,
FC.completed_date,
MGR.completed_date
...
)task

因此“budget.completed_date”现在可以称为“task.completed_date”。 pc.completed_date 和 mgr.completed_date 等也可以。这就是它的困惑。只是别名:

SELECT 
BUDGET.protocol_id  as budget_protocol_id
BUDGET.completed_date as budget_completed_date,
    SELECT 
BUDGET.protocol_id, BUDGET.completed_date,
CONTRACT.completed_date as contract_completed_date,
REQUEST.completed_date as request_completed_date,
RECEIVE.completed_date as receive_completed_date,
etc
...
)task

这将使每个 task.complete_date 保持唯一,您可以从那里将它们称为 task.budget_completed_date。有意义吗?

【讨论】:

  • 你明白了。别名是问题。仍然是一个非常缓慢的操作,但我稍后会进行优化。谢谢
  • 查看 Gordon 的答案以提高速度……当它可以更有效地完成时,您几乎可以在这里进行 7 次全表扫描。您在这里所做的也可以被认为是“透视”或“交叉表”,这取决于您使用的数据库,可以使用更有效的方式来使用它。
【解决方案3】:

如果需要在子查询中访问子查询的列,那么只需在中间子查询的SELECT 中使用它们:

 SELECT middle_subquery.c1
 FROM 
 (
    SELECT inner_subquery.c1
    FROM
    (
       SELECT count(*) c1 FROM tab
    ) inner_subquery
 ) middle_subquery

而不是

 SELECT middle_subquery.inner_subquery.c1
 FROM 
 (
    SELECT *
    FROM
    (
       SELECT count(*) c1 FROM tab
    ) inner_subquery
 ) middle_subquery

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 2020-04-03
    • 2021-02-23
    • 2018-04-11
    相关资源
    最近更新 更多