【问题标题】:How to use properly JOIN condition with Subquery in WHERE?如何在 WHERE 中正确使用子查询的 JOIN 条件?
【发布时间】:2014-10-29 10:36:16
【问题描述】:

目前我的架构如下所示:

CREATE TABLE IF NOT EXISTS `hours` (
  `Project_ID` varchar(10) NOT NULL,
  `Project_Name` varchar(50) NOT NULL,
  `Res_ID` varchar(40) NOT NULL,
  `Date` date NOT NULL,
  `Hours` int(10) NOT NULL,
)

CREATE TABLE IF NOT EXISTS `project_resources` (
  `Project_ID` varchar(10) NOT NULL,
  `Res_ID` varchar(40) NOT NULL
)

//A single project Id can be assosiated with many resource id's

CREATE TABLE IF NOT EXISTS `resources` (
  `Res_ID` varchar(40) NOT NULL,
  `Res_Name` varchar(50) NOT NULL,
  `Email` varchar(50) NOT NULL,
  `Phone_Number` bigint(12) NOT NULL,
  `Reporting_Manager` varchar(50) NOT NULL,
  `Role` varchar(50) NOT NULL,
  `Designation` varchar(50) NOT NULL,
  `Password` varchar(50) NOT NULL
)

我在这里尝试生成一个查询,以便它以以下格式显示数据,

资源名称 |总和(小时)。

我尝试执行以下查询

SELECT res_name,sum(hours) FROM hours h
INNER JOIN resources r ON h.res_id=r.res_id
  WHERE r.res_id = (SELECT res_id FROM `project_resources` WHERE project_id='someproject')

我知道这返回子查询返回超过 1 行错误。但我只是想知道我能做些什么来让这个查询正确。

【问题讨论】:

  • 你的表的主键在哪里?
  • 对不起,我忘记了,hours 表的主键是('project_id','res_id','date') 的组合。对于project_resources 表的主键是('project_id ','res_id') 和 resources 表的主键是 'res_id'

标签: php mysql sql database join


【解决方案1】:

我想这会对你有所帮助

Select res_name,sum(hours) 
from hours h inner join resources r on h.res_id=r.res_id 
where r.res_id IN (
      SELECT res_id 
      FROM `project_resources` 
      WHERE project_id='someproject'
)

如果您的子查询返回超过 1 行,您可以在 where 语句中使用 'IN' 子句

【讨论】:

  • 表格的键在哪里?
【解决方案2】:

你可以使用in:

Select res_name,sum(hours) 
from hours h inner join
     resources r
     on h.res_id = r.res_id 
where r.res_id in (SELECT res_id 
                   FROM `project_resources` 
                   WHERE project_id = 'someproject'
                  );

但是,我可能建议只进行多个连接:

Select res_name,sum(hours) 
from hours h inner join
     resources r
     on h.res_id = r.res_id inner join
     project_resources pr
     on pr.res_id = r.res_id and pr.project_id = 'someproject'

当然,如果project_resources 表中有重复项,这将不起作用。

【讨论】:

  • @Begueradj。 . .我不明白你的问题。 SQL 查询独立于键定义。主键和其他类型的索引可以提高性能。
【解决方案3】:

所以基本上,你想展示两件事:

  1. 资源名称
  2. 资源工作的总小时数

前提是你的Res_IDproject_resources表中,项目id为'someproject'

对吗?

那我们把这个问题分解成三个小部分:

第 1 部分:

要获取资源的名称,您应该编写:

SELECT rs.Res_Name
FROM resources rs

注意rs是表resources的别名。

好吗?

现在第 2 部分:

要获得资源工作的总小时数,您应该编写:

SELECT SUM(Hours)
FROM hours h

基本上,h 是表hours 的别名。我想你明白了,对吧?

最后,第 3 部分:

您的Project_ID 应该是'someproject'

另外,Res_ID 应该在 project_resources 内。

现在,让我们将所有部分连接在一起。现在我们得到:

 SELECT r.Res_Name, SUM(Hours)
 FROM hours h
 INNER JOIN resources r ON h.Res_ID = r.Res_ID
 INNER JOIN project_resources pr ON r.Res_ID = pr.Res_ID
 WHERE pr.Project_ID = 'someproject'

基本上,在这里我们首先加入hoursresources,因为Res_ID 在两个表中是相同的,我们也加入了resourcesproject_resources 表,因为Res_ID在两个表中都相同,并且hours 中的Project_ID'someproject'

希望这会给你你想要的。你明白了吧?

但是,请注意。我注意到您对表 hours 使用相同的名称,它是列 Hours。虽然,由于名称的大小写不同,这不会引起任何问题,但这并不是一个真正的好习惯。您应该为您的列想一个不同的、有意义的名称,以避免混淆和任何类型的意外事件。享受编码!!!

【讨论】:

    【解决方案4】:

    您正在选择“someproject”中(也)使用的所有项目及其资源的总小时数。由于与“someproject”关联的资源可能不止一个,因此请使用 IN 获取所有资源。那么……

    • 要么 按 res_name 分组(前提是它是唯一的,否则使用 res_id)以获取每个资源的结果记录
    • 从结果中删除 res_name(因为当有多个时,您只会随机显示其中一个)
    • 使用 GROUP_CONCAT 生成一个包含所有资源名称的字符串

    所以要么:

    SELECT 
      res_name,
      sum(hours) 
    FROM hours h
    INNER JOIN resources r ON h.res_id=r.res_id
    WHERE r.res_id IN 
    (
      SELECT res_id 
      FROM `project_resources` 
      WHERE project_id='someproject'
    )
    GROUP BY res_id;
    

    或者:

    SELECT 
      GROUP_CONCAT(res_name) AS res_names,
      sum(hours) 
    FROM hours h
    INNER JOIN resources r ON h.res_id=r.res_id
    WHERE r.res_id IN
    (
      SELECT res_id 
      FROM `project_resources` 
      WHERE project_id='someproject'
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多