Mysql 循环浏览表格的每条记录,并对所有其他记录执行计算
我想在我的表Mysql 循环浏览表格的每条记录,并对所有其他记录执行计算,mysql,sql,Mysql,Sql,我想在我的表工作 无最高评级的计算方法为: 对于每一行,从该记录的ANNDATS\u CONVERTED中获取上一年内的所有其他行,并具有与该记录相同的ESTIMID 从中找到最低的IRECD值 然后,计算相同的分析员拥有与计算出的最低IRECCD匹配的IRECCD的次数 注意:这应忽略正在计算的当前行(以便找到行id 1的值,在计算中不要使用此行),并且应完全忽略ANALYST为空的任何记录 表工作: | ID | ANALYST | ESTIMID | ANNDATS_
工作
无最高评级的计算方法为:
- 对于每一行,从该记录的
ANNDATS\u CONVERTED
中获取上一年内的所有其他行,并具有与该记录相同的ESTIMID
- 从中找到最低的
IRECD
值
- 然后,计算相同的
分析员
拥有与计算出的最低IRECCD
匹配的IRECCD的次数
注意:这应忽略正在计算的当前行(以便找到行id 1的值,在计算中不要使用此行),并且应完全忽略ANALYST
为空的任何记录
表工作
:
| 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 | |
| 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 |
因此-当计算无最高评级时,记录#1:
- 记录#1将不包括在计算中,因为我想从计算中省略它
- 记录#7将根本不包含在计算中,因为
分析师
为空
- 记录#8将不包括在计算中,因为
ESTIMID
与记录#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 | |
| 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 |
以下是我目前拥有的MySQL:
UPDATE `working`
SET `working`.`NO_TOP_RATING` =
(
SELECT COUNT(`ID`) FROM (SELECT `ID`,`IRECCD`,`ESTIMID` FROM `working`) AS BB
WHERE
`IRECCD` =
(
SELECT COUNT(`ID`) FROM (SELECT `ID`,`IRECCD`,`ESTIMID`, `ANALYST` FROM `working`) AS ZZ
WHERE
`IRECCD` =
-- this calculates the LOWEST number with same `ESTIMID`
(
SELECT MIN(`IRECCD`)
FROM (SELECT `ID`,`IRECCD`,`ANNDATS_CONVERTED`,`ESTIMID` FROM `working`) AS CC
WHERE
`ANNDATS_CONVERTED` >= DATE_SUB(`ANNDATS_CONVERTED`,INTERVAL 1 YEAR)
AND
`working`.`ESTIMID` = BB.`ESTIMID`
)
-- END this calculates the LOWEST number with same `ESTIMID`
AND
`working`.`ANALYST` = ZZ.`ANALYST`
)
)
WHERE `working`.`ANALYST` != ''
这是在PHP中工作的,循环遍历每个记录并评估每个记录的所有其他记录。这涉及到循环,在大型数据库上需要很长时间。我试图用MySQL获得同样的结果。我采取了一些步骤来解决这个问题。我做的第一件事就是编写一个JOIN
,它得到了我需要的所有行。我在几个条件下加入了表格:
- 这场比赛的结果是一致的
- id值不相同
- 两个表中的analyst列均不为null
- 一个表的anndats_转换值在另一个表的上一年内
为了进行测试,我从两个表中选择了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 |
一个简短的结果集显示了以下配对:
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行为不同的估计值
然后,我使用聚合函数通过按第一个表分组来计算最小IRECD:
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 |
我看到了每个人所有可能的配对,如下所示:
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\u ireccd
将为空
我做的最后一件事是使用该结果集,并计算IRECD与min_IRECD匹配的次数。我按id分组,因此在上面的示例集中,它从不匹配,因此计数为0。这是最后一个查询。它将null值(第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;
以下是我得到的结果:
您能否编辑您的问题,以包含您共享的样本数据的预期结果?仍然存在一些混淆。例如,您希望行位于日期后一年内还是日期前一年内?因此,在计算第#1行的值时,是否应包括第#2行,因为它发生在第#1行之前?谢谢@McAdam331。符合条件的年份应为转换后的>=-1年。因此,一年前,直到ANNDATS\u转换为
。是-第2行将被包括在内,因为它在等于或大于1年前的范围内。是@McAdam331我将编辑问题以显示预期结果。谢谢你的帮助。你好,谢谢。我有一个问题的想法,但我想确保答案是正确的。谢谢@McAdam331您的回答。我一定会把这件事仔细研究一遍。我真的很感谢您的时间:)@kreevp有什么进展吗?当我看到您的结果表显示“1”作为记录(5),而不是记录(6)时,我有点不知所措,因为在我给出的示例中应该是这样的。