0

在 MySql 数据库中,我必须进行一些棘手的查询。我必须只在两列中得到结果(类型(项目、支持、教育)和价值(例如 60 和 40))

我有包含类型的静态表:

T1

ID  TYPE
1   PROJECT
2   PROJECT
3   PROJECT
4   SUPPORT
5   EDUCATION

我有静态表 T2,其中包含具有某些类型值的所有任务:

    T2

  TASK    T1ID

    1      1
    2      1
    3      2
    4      3 
    5      4
    6      5

T3 是带有一些 IDS 的已创建任务的动态表。

T3 

ID
1
2
3
4
5
6

T4 表包含谁创建了这些任务的信息。

T4

T3ID     Name
1       Bob Marley
2       Bob Marley
3       Bob Marley
4       Bob Marley
5       Tom Cruise
6       Bob Marley

最后 T5 包含来自 T2 和 T3 的信息

T5

TASK    T3ID
  1       1
  2       2
  3       3
  5       4
  1       5
  5       6

对于某些特定的人(总是一个人——在这个例子中是 Bob Marley 或 Tom Cruise),我必须以百分比统计他们在项目、支持或教育方面工作了多少。

所以我会选择 Bob Marley——他的 T3ID 是 1、2、3、4 和 6。

在表 5 中,他的任务 ID 是 1、2、3、5 和 5。

因此,当我查看表 T2 时,他的 T1 ID 是 1、1、2、4 和 4。这意味着 Bob Marley 从事 3 个项目和 2 个支持任务。

所以当我选择 Bob Marley 时,结果应该是:

PROJECT  60
SUPPORT  40

这是查询的最终结果。我怎样才能做到这一点?我知道它必须是几个 JOIN 语句,当然你可以在 WHERE 子句中使用

where name='Bob Marley'

如果我把

 `where name=Tom Cruise

结果应该是

PROJECT 100`

谢谢

4

1 回答 1

4

我认为这就是你要找的:

SELECT 
  t4.Name,
  SUM(CASE WHEN t1.type = 'PROJECT'   THEN 1 ELSE 0 END) * 100 / COUNT(t1.type) Project,
  SUM(CASE WHEN t1.type = 'SUPPORT'   THEN 1 ELSE 0 END) * 100 / COUNT(t1.type) SUPPORT,
  SUM(CASE WHEN t1.type = 'EDUCATION' THEN 1 ELSE 0 END) * 100 / COUNT(t1.type) Education
FROM T1
INNER JOIN T2 ON t1.ID = t2.T1ID
INNER JOIN t5 ON t2.task = t5.task
INNER JOIN t3 ON t3.id = t5.t3id
INNER JOIN t4 ON t3.Id = t4.t3id
GROUP BY t4.Name;

SQL 小提琴演示

这会给你:

|       NAME | PROJECT | SUPPORT | EDUCATION |
----------------------------------------------
| Bob Marley |      60 |      40 |         0 |
| Tom Cruise |     100 |       0 |         0 |

对于您发布的示例数据。

请注意:这只会为您Name提供项目和任务中涉及的内容。您可能需要OUTER JOIN(LEFT or RIGHT)在表中而不是INNER JOIN包含那些Name未参与任何任务或项目的 s(不匹配的行),用IFNULL()to 替换NULLs 为零。


更新:

您可以使用该CONCAT()函数来执行此操作,但如果您将先前的查询包含在子查询中并在外部查询中执行此操作,则会更容易和更易读,如下所示:

SELECT
  Name,
  CONCAT(CAST(project   AS DECIMAL(10, 2)), ' AND ', 
         CAST(support   AS DECIMAL(10, 2)), ' AND ', 
         CAST(education AS DECIMAL(10, 2))) AS Percentage
FROM
(
  SELECT 
    t4.Name,
    SUM(CASE WHEN t1.type = 'PROJECT' THEN 1 ELSE 0 END) * 100 / COUNT(t1.type) Project,
    SUM(CASE WHEN t1.type = 'SUPPORT' THEN 1 ELSE 0 END) * 100 / COUNT(t1.type) SUPPORT,
    SUM(CASE WHEN t1.type = 'EDUCATION' THEN 1 ELSE 0 END) * 100 / COUNT(t1.type) Education
  FROM T1
  INNER JOIN T2 ON t1.ID = t2.T1ID
  INNER JOIN t5 ON t2.task = t5.task
  INNER JOIN t3 ON t3.id = t5.t3id
  INNER JOIN t4 ON t3.Id = t4.t3id
  GROUP BY t4.Name
) t;

更新的 SQL Fiddle 演示

这会给你:

|       NAME |               PERCENTAGE |
-----------------------------------------
| Bob Marley | 60.00 AND 40.00 AND 0.00 |
| Tom Cruise | 100.00 AND 0.00 AND 0.00 |

您可以添加WHERE子句以将此值限制为仅WHERE Name = 'Some name'在外部查询或子查询中的任何用户名。


更新 2

好的,对不起,我错过了。不需要PIVOTorCONCAT()或动态 SQL 来执行此操作。你可以这样做:

SELECT 
  t1.type,
  COUNT(t2.task) * 100 / 
  (SELECT COUNT(*)
   FROM T4 t 
   WHERE t4.Name = t.Name) AS Percentage
FROM T1
INNER JOIN T2 ON t1.ID = t2.T1ID
INNER JOIN t5 ON t2.task = t5.task
INNER JOIN t3 ON t3.id = t5.t3id
INNER JOIN t4 ON t3.Id = t4.t3id
WHERE t4.Name = 'Bob Marley' 
GROUP BY t4.Name, t1.type;

更新的 SQL Fiddle 演示

这会给你:

|    TYPE | PERCENTAGE |
------------------------
| PROJECT |         60 |
| SUPPORT |         40 |
于 2013-01-05T13:51:12.477 回答