Mysql 分组依据和自定义订单
我已经通读了上的答案,但将其应用到我的查询中,结果是在一个相当简单的情况下,子查询中有一个子查询,因此我想知道这是否可以简化: 带有示例数据的模式 为简洁起见,我省略了Mysql 分组依据和自定义订单,mysql,group-by,sql-order-by,mysql-5.7,mysql-5.1,Mysql,Group By,Sql Order By,Mysql 5.7,Mysql 5.1,我已经通读了上的答案,但将其应用到我的查询中,结果是在一个相当简单的情况下,子查询中有一个子查询,因此我想知道这是否可以简化: 带有示例数据的模式 为简洁起见,我省略了members表中的其他字段。此外,在实际应用程序中还有更多的表被连接,但是这些表很容易连接。给我带来问题的是成员资格\u堆栈表 CREATE TABLE members ( id int unsigned auto_increment, first_name varchar(255) not null, PRIMAR
members
表中的其他字段。此外,在实际应用程序中还有更多的表被连接,但是这些表很容易连接。给我带来问题的是成员资格\u堆栈
表
CREATE TABLE members (
id int unsigned auto_increment,
first_name varchar(255) not null,
PRIMARY KEY(id)
);
INSERT INTO members (id, first_name)
VALUES (1, 'Tyler'),
(2, 'Marissa'),
(3, 'Alex'),
(4, 'Parker');
CREATE TABLE membership_stack (
id int unsigned auto_increment,
member_id int unsigned not null,
sequence int unsigned not null,
team varchar(255) not null,
`status` varchar(255) not null,
PRIMARY KEY(id),
FOREIGN KEY(member_id) REFERENCES members(id)
);
-- Algorithm to determine correct team:
-- 1. Only consider rows with the highest sequence number
-- 2. Order statuses and pick the first one found:
-- (active, completed, cancelled, abandoned)
INSERT INTO membership_stack (member_id, sequence, team, status)
VALUES (1, 1, 'instinct', 'active'),
(1, 1, 'valor', 'abandoned'),
(2, 1, 'valor', 'active'),
(2, 2, 'mystic', 'abandoned'),
(2, 2, 'valor', 'completed'),
(3, 1, 'instinct', 'completed'),
(3, 2, 'valor', 'active');
我无法更改数据库架构,因为数据与外部数据源同步
查询
这就是我到目前为止所做的:
SELECT m.id, m.first_name, ms.sequence, ms.team, ms.status
FROM membership_stack AS ms
JOIN (
SELECT member_id, MAX(sequence) AS sequence
FROM membership_stack
GROUP BY member_id
) AS t1
ON ms.member_id = t1.member_id
AND ms.sequence = t1.sequence
RIGHT JOIN members AS m
ON ms.member_id = m.id
ORDER BY m.id, FIELD(ms.status, 'active', 'completed', 'cancelled', 'abandoned');
这与预期的一样有效,但如果成员的“最新序列”涉及多个团队,则成员可能会出现多次。我需要做的是在id
上再次聚合,然后选择每组中的第一行
然而,这带来了一些问题:
字段(ms.status,'active','completed','cancelled','dependend')
是否被视为此结果集的功能相关字段。查询还需要与MySQL 5.1兼容,因为这就是我们目前正在运行的编辑:我注意到有些成员不属于任何团队。这些成员应包含在结果集中,这些字段的值为空。问题已更新以反映新信息。我会使用变量进行此操作 您正在寻找一个
membership\u stack
行,该行对于您的特殊订购是最大的。我只关注这一点。join
返回到members
是微不足道的
select ms.*
from (select ms.*,
(@rn := if(@m = member_id, @rn + 1,
if(@m := member_id, 1, 1)
)
) as rn
from membership_stack ms cross join
(select @m := -1, @rn := 0) params
order by member_id, sequence desc,
field(ms.status, 'active', 'completed', 'cancelled', 'abandoned')
) ms
where rn = 1;
变量是逻辑的实现方式。排序是获得正确结果的关键
编辑:
MySQL对子查询中的限制非常挑剔。这可能会起作用:
select ms.*
from membership_stack ms
where (sequence, status) = (select ms2.sequence, ms2.status
from membership_stack ms2
where ms2.member_id = ms.member_id
order by ms2.member_id, ms2.sequence desc,
field(ms2.status, 'active', 'completed', 'cancelled', 'abandoned')
limit 1
);
您可以在WHERE子句中使用限制为1的相关子查询:
SELECT m.id, m.first_name, ms.sequence, ms.team, ms.status
FROM members AS m
JOIN membership_stack AS ms ON ms.member_id = m.id
WHERE ms.id = (
SELECT ms1.id
FROM membership_stack AS ms1
WHERE ms1.member_id = ms.member_id
ORDER BY ms1.sequence desc,
FIELD(ms1.status, 'active', 'completed', 'cancelled', 'abandoned'),
ms1.id asc
LIMIT 1
)
ORDER BY m.id;
演示:
更新
要包括成员资格\u stack
表中没有条目的成员,应使用左连接,并将子查询条件从WHERE子句移动到ON子句:
SELECT m.id, m.first_name, ms.sequence, ms.team, ms.status
FROM members AS m
LEFT JOIN membership_stack AS ms
ON ms.member_id = m.id
AND ms.id = (
SELECT ms1.id
FROM membership_stack AS ms1
WHERE ms1.member_id = ms.member_id
ORDER BY ms1.sequence desc,
FIELD(ms1.status, 'active', 'completed', 'cancelled', 'abandoned'),
ms1.id asc
LIMIT 1
)
ORDER BY m.id;
演示:是的,我明白了。再次尝试理解您的问题。我已编辑我的问题,以包括成员可能在成员资格堆栈中没有任何条目的情况。有没有办法使这个查询适应这些情况?或者将WHERE
条件放入带有左连接的ON
子句中是否有任何问题?@rink.attendant.6使用左连接。检查更新。如果序列和状态相同怎么办?例子Tyler@valor状态为“活动”吗?@PaulSpiegel我也对此提出了质疑,但数据提供商还没有回复这是否可能。同一序列中不应同时有多个活动的
,但我认为如果它们在同一序列中连续进行,则可能有多个完成的
。但是,您应该定义一个“不同”的顺序。在我的解决方案中,我使用membership\u stack.id ASC
作为ORDER BY子句中的最后一列(以防万一)。子查询中的WHERE with LIMIT在“WHERE子句”中生成一个错误未知列“field”
。变量1似乎工作正常,请您进一步解释,以便我能理解并向其他人提出解决方案好吗?@rink.attendant.6。您似乎熟悉窗口功能。这相当于MySQL中的row_number()(按成员id按字段(…)进行分区)
。变量逐行跟踪状态。(第二个查询中的错误是列名键入错误。)实际上我从未听说过窗口函数。我只看到row_number()
来自试图解决这个问题的人,他曾使用过另一种RDBMS。无论如何,我将与我的团队讨论这个问题,并希望在下周的某个时候接受解决方案。
SELECT m.id, m.first_name, ms.sequence, ms.team, ms.status
FROM members AS m
LEFT JOIN membership_stack AS ms
ON ms.member_id = m.id
AND ms.id = (
SELECT ms1.id
FROM membership_stack AS ms1
WHERE ms1.member_id = ms.member_id
ORDER BY ms1.sequence desc,
FIELD(ms1.status, 'active', 'completed', 'cancelled', 'abandoned'),
ms1.id asc
LIMIT 1
)
ORDER BY m.id;