我想在我的表NO_TOP_RATING
working
的值
NO_TOP_RATING
的计算方法是:
ANNDATS_CONVERTED
之前的所有其他行,并且与该记录具有相同的ESTIMID
。IRECCD
值。ANALYST
的{{1}}与所计算的最低IRECCD
相匹配的次数。 注意:这应该省略正在计算的当前行(因此要查找行ID 1的值,不要在计算中使用此行)以及IRECCD
所在的任何记录应该完全忽略空白。
表ANALYST
:
working
所以 - 在为记录#1 计算 | ID | ANALYST | ESTIMID | ANNDATS_CONVERTED | IRECCD | NO_TOP_RATING |
---------------------------------------------------------------------------------
| 1 | DAVE | Brokerage000 | 1998-07-01 | 2 | |
| 2 | DAVE | Brokerage000 | 1998-06-28 | 2 | |
| 3 | DAVE | Brokerage000 | 1998-07-02 | 4 | |
| 4 | DAVE | Brokerage000 | 1998-07-04 | 3 | |
| 5 | SAM | Brokerage000 | 1998-06-14 | 1 | |
| 6 | SAM | Brokerage000 | 1998-06-28 | 4 | |
| 7 | | Brokerage000 | 1998-06-28 | 1 | |
| 8 | DAVE | Brokerage111 | 1998-06-28 | 5 | |
时:
NO_TOP_RATING
为空白ANALYST
与记录#1不同预期结果:
表ESTIMID
:
working
这是我到目前为止的MySQL:
| ID | ANALYST | ESTIMID | ANNDATS_CONVERTED | IRECCD | NO_TOP_RATING |
---------------------------------------------------------------------------------
| 1 | DAVE | Brokerage000 | 1998-07-01 | 2 | 0 |
| 2 | DAVE | Brokerage000 | 1998-06-28 | 2 | 0 |
| 3 | DAVE | Brokerage000 | 1998-07-02 | 4 | 0 |
| 4 | DAVE | Brokerage000 | 1998-07-04 | 3 | 0 |
| 5 | SAM | Brokerage000 | 1998-06-14 | 1 | 0 |
| 6 | SAM | Brokerage000 | 1998-06-28 | 4 | 1 |
| 7 | | Brokerage000 | 1998-06-28 | 1 | |
| 8 | DAVE | Brokerage111 | 1998-06-28 | 5 | 0 |
这适用于PHP,循环遍历每条记录并评估每条记录的所有其他记录。这涉及循环并在大型数据库上花费很长时间。我试图用MySQL实现相同的结果。
答案 0 :(得分:2)
我采取了一些措施来解决这个问题。我做的第一件事是写一个JOIN
,它得到了我需要的所有行。我在几个条件下加入了这个表:
为了测试,我从两个表中选择了id以确保我得到了正确的配对:
SELECT w.id, wo.id
FROM working w
JOIN working wo
ON w.estimid = wo.estimid
AND w.id != wo.id
AND w.analyst IS NOT NULL
AND wo.analyst IS NOT NULL
AND wo.anndats_converted BETWEEN DATE_SUB(w.anndats_converted, INTERVAL 1 YEAR) AND w.anndats_converted
ORDER BY w.id;
简短的结果集显示以下配对:
| id | id |
+----+----+
| 1 | 2 |
| 1 | 5 |
| 1 | 6 |
| 2 | 5 |
| 2 | 6 |
这似乎符合您的要求。对于id#1,排除第1行(因为正在计算)第3行和第4行不在正确的日期范围内,第7行为空,第8行是不同的estimid。
然后,我使用聚合函数通过第一个表分组来计算最小ireccd:
SELECT w.id, w.analyst, MIN(wo.ireccd) AS min_ireccd
FROM working w
JOIN working wo
ON w.estimid = wo.estimid
AND w.id != wo.id
AND w.analyst IS NOT NULL
AND wo.analyst IS NOT NULL
AND wo.anndats_converted BETWEEN DATE_SUB(w.anndats_converted, INTERVAL 1 YEAR) AND w.anndats_converted
GROUP BY w.id;
下一部分也很棘手,所以我将分两步解释。我使用原始表加入了上述查询,其中唯一的条件是分析师列匹配。这样做是在某种程度上创造了笛卡尔积。查询看起来像这样:
SELECT *
FROM working w
LEFT JOIN(
SELECT w.id, w.analyst, MIN(wo.ireccd) AS min_ireccd
FROM working w
LEFT JOIN working wo
ON w.estimid = wo.estimid
AND w.id != wo.id
AND w.analyst IS NOT NULL
AND wo.analyst IS NOT NULL
AND wo.anndats_converted BETWEEN DATE_SUB(w.anndats_converted, INTERVAL 1 YEAR) AND w.anndats_converted
GROUP BY w.id) temp ON temp.analyst = w.analyst;
我看到每个人都有可能的配对,如下:
| id | analyst | ireccd | id | analyst | min_ireccd |
+----+---------+--------+----+---------+------------+
| 1 | DAVE | 2 | 8 | DAVE | null |
| 1 | DAVE | 2 | 4 | DAVE | 1 |
| 1 | DAVE | 2 | 1 | DAVE | 1 |
| 1 | DAVE | 2 | 2 | DAVE | 1 |
| 1 | DAVE | 2 | 3 | DAVE | 1 |
请注意,将第一个DAVE
与表格中DAVE
的所有其他行进行比较。 另请注意我更改了上面的内部查询以包含外部联接,以便考虑所有行。如果没有要计算的内容,min_ireccd
将为空。
我做的最后一件事是使用该结果集,并计算ireccd与min_ireccd匹配的次数。我按id分组,所以在上面的示例集中,它从不匹配,因此计数将为0.这是最终查询。它将空值(第7行)保留为null,因为这是您的预期结果显示的内容:
SELECT w.*, SUM(w.ireccd = temp.min_ireccd) AS NO_TOP_RATING
FROM working w
LEFT JOIN(
SELECT w.id, w.analyst, MIN(wo.ireccd) AS min_ireccd
FROM working w
LEFT JOIN working wo
ON w.estimid = wo.estimid
AND w.id != wo.id
AND w.analyst IS NOT NULL
AND wo.analyst IS NOT NULL
AND wo.anndats_converted BETWEEN DATE_SUB(w.anndats_converted, INTERVAL 1 YEAR) AND w.anndats_converted
GROUP BY w.id) temp ON temp.analyst = w.analyst
GROUP BY w.id;
这些是我得到的结果: