MySQL Select 匹配分组依据值的整行
MySQL Select entire row from matching Group By value
假设我有 2 个这样的表:
MyTable1:
Name ID Timestamp TestNum Grade
Alex 1101 2020-10-01 12:00:00 1 85
Alex 1101 2020-10-02 13:00:00 2 90
Alex 1101 2020-10-03 8:00:00 3 95
Alex 1101 2020-10-04 10:00:00 4 90
MyTable2:
ID Avg StDev
1101 90 4.08
我正在尝试获取第一个(时间戳)实例的行,其中成绩相差 X 个标准差。
ExpectedResults:
Name ID Timestamp TestNum StDevsAway
Alex 1101 2020-10-01 12:00:00 1 -1.23
Alex 1101 2020-10-02 13:00:00 2 0
Alex 1101 2020-10-03 8:00:00 3 1.23
不应返回第 4 行,因为它的 Standard Deviations Away 已经在之前的时间戳中找到。
我对 MySQL 还是很陌生,但这是我目前所处的位置:
select a.Name
, a.ID
, a.Timestamp
, a.TestNum
, round( ( a.Grade - b.Avg ) / b.StDev, 2 ) as StDevsAway
from MyTable1 as a
join MyTable2 as b
on a.ID = b.ID
group
by round( ( a.Grade - b.Avg ) / b.StDev, 2 );
我认为问题只是为每个 id/grade tupe 找到“第一”行。所以(假设 MySQL 8.0):
select t1.*
from (
select t1.*, row_number() over(partition by id, grade order by timestamp) rn
from mytable1 t1
) t1
where rn = 1
然后,如果您愿意,可以将第二个 table 带入连接:
select t1.*, round(t1.grade - t2.avg) / t2.stdev, 2) stdevsaway
from (
select t1.*, row_number() over(partition by id, grade order by timestamp) rn
from mytable1 t1
) t1
inner join mytable2 t2 on t2.id = t1.id
where rn = 1
在早期版本中,您可以使用子查询进行过滤:
select t1.*, round(t1.grade - t2.avg) / t2.stdev, 2) stdevsaway
from mytable1 t1
inner join mytable2 t2 on t2.id = t1.id
where t1.timestamp = (
select min(t11.timestamp) from mytable1 t11 where t11.id = t1.id and t11.grade = t1.grade
)
在以前的 Versin 中,当然在 mysql8 中你也可以这样做。
这将排除该用户的每个测试编号,即 gas 标准偏差,第一个除外
架构 (MySQL v5.5)
CREATE TABLE MyTable1 (
`Name` VARCHAR(4),
`ID` INTEGER,
`Timestamp` DATETIME,
`TestNum` VARCHAR(7),
`Grade` INTEGER
);
INSERT INTO MyTable1
(`Name`, `ID`, `Timestamp`, `TestNum`, `Grade`)
VALUES
('Alex', '1101', '2020-10-01 12:00:00', '1', '85'),
('Alex', '1101', '2020-10-02 13:00:00', '2', '90'),
('Alex', '1101', '2020-10-03 08:00:00', '3','95'),
('Alex', '1101', '2020-10-04 10:00:00', '4', '90');
CREATE TABLE MyTable2 (
`ID` INTEGER,
`Avg` INTEGER,
`StDev` FLOAT
);
INSERT INTO MyTable2
(`ID`, `Avg`, `StDev`)
VALUES
('1101', '90', '4.08');
查询 #1
select
a.Name
, a.ID
, a.Timestamp
, a.TestNum
, round( ( a.Grade - b.Avg ) / b.StDev, 2 ) as StDevsAway
from MyTable1 as a join MyTable2 as b on a.ID = b.ID
WHERE
TestNum NOT IN (SELECT TestNum
FROM MyTable1 c
WHERE c.`ID` = a.`ID`
AND c.`Grade` = b.Avg
AND c.`TestNum`<> (SELECT MIN(TestNum)
FROM MyTable1 d
WHERE d.`ID` = a.`ID`
AND d.`Grade` = b.Avg)
);
| Name | ID | Timestamp | TestNum | StDevsAway |
| ---- | ---- | ------------------- | ------- | ---------- |
| Alex | 1101 | 2020-10-01 12:00:00 | 1 | -1.23 |
| Alex | 1101 | 2020-10-02 13:00:00 | 2 | 0 |
| Alex | 1101 | 2020-10-03 08:00:00 | 3 | 1.23 |
假设我有 2 个这样的表:
MyTable1:
Name ID Timestamp TestNum Grade
Alex 1101 2020-10-01 12:00:00 1 85
Alex 1101 2020-10-02 13:00:00 2 90
Alex 1101 2020-10-03 8:00:00 3 95
Alex 1101 2020-10-04 10:00:00 4 90
MyTable2:
ID Avg StDev
1101 90 4.08
我正在尝试获取第一个(时间戳)实例的行,其中成绩相差 X 个标准差。
ExpectedResults:
Name ID Timestamp TestNum StDevsAway
Alex 1101 2020-10-01 12:00:00 1 -1.23
Alex 1101 2020-10-02 13:00:00 2 0
Alex 1101 2020-10-03 8:00:00 3 1.23
不应返回第 4 行,因为它的 Standard Deviations Away 已经在之前的时间戳中找到。
我对 MySQL 还是很陌生,但这是我目前所处的位置:
select a.Name
, a.ID
, a.Timestamp
, a.TestNum
, round( ( a.Grade - b.Avg ) / b.StDev, 2 ) as StDevsAway
from MyTable1 as a
join MyTable2 as b
on a.ID = b.ID
group
by round( ( a.Grade - b.Avg ) / b.StDev, 2 );
我认为问题只是为每个 id/grade tupe 找到“第一”行。所以(假设 MySQL 8.0):
select t1.*
from (
select t1.*, row_number() over(partition by id, grade order by timestamp) rn
from mytable1 t1
) t1
where rn = 1
然后,如果您愿意,可以将第二个 table 带入连接:
select t1.*, round(t1.grade - t2.avg) / t2.stdev, 2) stdevsaway
from (
select t1.*, row_number() over(partition by id, grade order by timestamp) rn
from mytable1 t1
) t1
inner join mytable2 t2 on t2.id = t1.id
where rn = 1
在早期版本中,您可以使用子查询进行过滤:
select t1.*, round(t1.grade - t2.avg) / t2.stdev, 2) stdevsaway
from mytable1 t1
inner join mytable2 t2 on t2.id = t1.id
where t1.timestamp = (
select min(t11.timestamp) from mytable1 t11 where t11.id = t1.id and t11.grade = t1.grade
)
在以前的 Versin 中,当然在 mysql8 中你也可以这样做。
这将排除该用户的每个测试编号,即 gas 标准偏差,第一个除外
架构 (MySQL v5.5)
CREATE TABLE MyTable1 (
`Name` VARCHAR(4),
`ID` INTEGER,
`Timestamp` DATETIME,
`TestNum` VARCHAR(7),
`Grade` INTEGER
);
INSERT INTO MyTable1
(`Name`, `ID`, `Timestamp`, `TestNum`, `Grade`)
VALUES
('Alex', '1101', '2020-10-01 12:00:00', '1', '85'),
('Alex', '1101', '2020-10-02 13:00:00', '2', '90'),
('Alex', '1101', '2020-10-03 08:00:00', '3','95'),
('Alex', '1101', '2020-10-04 10:00:00', '4', '90');
CREATE TABLE MyTable2 (
`ID` INTEGER,
`Avg` INTEGER,
`StDev` FLOAT
);
INSERT INTO MyTable2
(`ID`, `Avg`, `StDev`)
VALUES
('1101', '90', '4.08');
查询 #1
select
a.Name
, a.ID
, a.Timestamp
, a.TestNum
, round( ( a.Grade - b.Avg ) / b.StDev, 2 ) as StDevsAway
from MyTable1 as a join MyTable2 as b on a.ID = b.ID
WHERE
TestNum NOT IN (SELECT TestNum
FROM MyTable1 c
WHERE c.`ID` = a.`ID`
AND c.`Grade` = b.Avg
AND c.`TestNum`<> (SELECT MIN(TestNum)
FROM MyTable1 d
WHERE d.`ID` = a.`ID`
AND d.`Grade` = b.Avg)
);
| Name | ID | Timestamp | TestNum | StDevsAway |
| ---- | ---- | ------------------- | ------- | ---------- |
| Alex | 1101 | 2020-10-01 12:00:00 | 1 | -1.23 |
| Alex | 1101 | 2020-10-02 13:00:00 | 2 | 0 |
| Alex | 1101 | 2020-10-03 08:00:00 | 3 | 1.23 |