0

我必须使用 4 个表生成报告,我尝试了很多连接,但我得到了错误的值:(

希望有人能帮助我。

员工分配表:

----------------------------
| Tid | StaffId | Planned  |
----------------------------
| 123 |   2     | 10:00:00 |
| 123 |   4     | 05:00:00 |
| 124 |   2     | 09:00:00 |
----------------------------

实际工作量表:

--------------------------------------------
| Tid | StaffId | ActualEffort  | logdate  |
--------------------------------------------
| 123 |   2     | 05:00:00      |2012-09-01|
| 123 |   4     | 05:00:00      |2012-09-01|
| 123 |   2     | 06:00:00      |2012-09-03|
| 124 |   2     | 09:00:00      |2012-09-04|
--------------------------------------------

项目清单表:

-------------------
| ProjectId | Tid |
-------------------
|    1      | 123 |
|    2      | 124 |
-------------------

项目名称表:

-------------------
| Id  | name      |
-------------------
| 1   | project1  |
| 2   | project2  |
-------------------

以下是我正在使用的查询:

SELECT P.id AS projectid,P.name,
SEC_TO_TIME(SUM(TIME_TO_SEC(A.planned)))planned,SEC_TO_TIME(SUM(TIME_TO_SEC(E.actualeffort)))actual FROM actualeffort E 
INNER JOIN staffassign A ON A.tid = E.tid
INNER JOIN projectlist L ON L.tid = A.tid
INNER JOIN projectname P ON P.id = L.projectid 
WHERE E.logdate BETWEEN FROM_UNIXTIME('1346475600') AND FROM_UNIXTIME('1348290000')
GROUP BY P.id

我得到这个:

---------------------------------------------
| projectid | name     | planned | actual   |
---------------------------------------------
|     1     | project1 | 15:00:00| 12:00:00 |
|     2     | project2 | 09:00:00| 09:00:00 |
---------------------------------------------

但它应该是这样的:

---------------------------------------------
| projectid | name     | planned | actual   |
---------------------------------------------
|     1     | project1 | 15:00:00| 16:00:00 |
|     2     | project2 | 09:00:00| 09:00:00 |
---------------------------------------------

我很困惑,我不知道我在哪里加入了错误。

有人请帮助我,我对此感到震惊。

4

3 回答 3

2

WHERE 过滤器可能是错误的。请注意,条件中的第一个日期时间从“08:00:00”开始 -

SELECT FROM_UNIXTIME('1346475600') dt1, FROM_UNIXTIME('1348290000') dt2;
+---------------------+---------------------+
| dt1                 | dt2                 |
+---------------------+---------------------+
| 2012-09-01 08:00:00 | 2012-09-22 08:00:00 |
+---------------------+---------------------+

的类型ActualEffortlogdate字段是日期;值“2012-09-01”小于“2012-09-01 08:00:00”。所以改变这个条件或使用 DATE 函数 -

WHERE
  E.logdate BETWEEN
  DATE(FROM_UNIXTIME('1346475600')) AND DATE(FROM_UNIXTIME('1348290000'))

(已编辑)

一方面,当您仅在列上加入时StaffAssign,您会得到一个迷你笛卡尔积,因为两个表都包含不止一行,并且没有其他特定条件可以建立 1:1 或最多, 1:N 行之间的关系。ActualEffortTidTid=123Tid

但事实上,1:N 也不会这样做:虽然它不会给您笛卡尔积效应,但它会导致一侧的值重复,从而导致 SUM 失真。

因此,inStaffAssign和 in 的数据ActualEffort必须分别聚合,然后加入,如下所示:

SELECT
  pl.ProjectId,
  pn.name,
  sa.Planned,
  ae.ActualEffort
FROM ProjectList pl
  JOIN ProjectName pn
    ON pn.Id = pl.ProjectId
  LEFT JOIN (SELECT Tid, SEC_TO_TIME(SUM(TIME_TO_SEC(Planned))) Planned FROM StaffAssign GROUP BY Tid) sa
    ON sa.Tid = pl.Tid
  LEFT JOIN (SELECT Tid, SEC_TO_TIME(SUM(TIME_TO_SEC(ActualEffort))) ActualEffort FROM ActualEffort GROUP BY Tid) ae
    ON ae.Tid = pl.Tid
 GROUP BY ProjectId;
于 2012-09-24T06:31:52.907 回答
1

您的 SQL 中有一个错误:您不想加入 p.ProjectID 而不是 p.id

于 2012-09-24T06:11:31.640 回答
0

试试这个查询

SELECT P.id AS projectid,P.name,
SEC_TO_TIME(SUM(TIME_TO_SEC(A.planned)))planned,SEC_TO_TIME(SUM(TIME_TO_SEC(E.actualeffort)))actual FROM actualeffort E 
INNER JOIN staffassign A ON A.tid = E.tid
INNER JOIN projectlist L ON L.tid = A.tid
INNER JOIN projectlist L ON L.tid = E.tid        // you have not added this line
INNER JOIN projectname P ON P.id = L.projectid 
WHERE E.logdate BETWEEN FROM_UNIXTIME('1346475600') AND FROM_UNIXTIME('1348290000')
GROUP BY P.id

L和之间的连接E应该存在。

于 2012-09-24T05:54:50.353 回答