创建包含具有条件的唯一行的新表; MySQL

Posted

技术标签:

【中文标题】创建包含具有条件的唯一行的新表; MySQL【英文标题】:Creating new table which contains unique rows with conditions ; MySQL 【发布时间】:2017-03-30 09:10:48 【问题描述】:

我有一个包含以下列的表格:

SessionID - 包含会话中的操作(假设每个 SessionID 1-10 行)

ActionName - 是动作的名称

时间 - 动作发生的时间

如果操作的名称是“a”或“b”,我需要返回一个新表,其列相同,并且每个 SessionID 仅包含 1 行。

也就是说,我的新表的每个 SessionID 应该有 1 行,其中包含操作“a”或“b”。

我试过了:

CREATE TABLE U_SessionID (
SELECT DISTINCT(SessionID) AS SessionID FROM test1)
;

我将唯一的会话复制到一个新表中

SELECT U_SessionID.SessionID, test1.ActionName, test1.SessionID
FROM test1
INNER JOIN U_SessionID ON (SELECT SessionID
FROM test1
WHERE U_SessionID.SessionID = test1.SessionID AND (ActionName = 
"a" OR ActionName = "b")
ORDER BY Time DESC
LIMIT 1);

但是这段代码导致 mysql 工作台崩溃(执行查询超时),我不知道它是否有效。

样本数据:

你能想出一个更轻松的查询来运行它吗?

也许更好的方法是:

    获取所有包含操作“a”或操作“b”的行:

SELECT * FROM test1 WHERE ActionName = "a" OR ActionName = "b";

    仅根据 SessionID 删除重复项(无论时间顺序如何)

对此有什么想法?

【问题讨论】:

我认为你的 on 子句不完整 您能给我们提供样本数据和预期结果吗? @Jens 添加,谢谢 在您的查询中,您在示例数据中仅引用了两个表?请也添加ddl 【参考方案1】:

会话 ID 的时间是否唯一?

如果是这样:-

SELECT U_SessionID.SessionID, test1.ActionName, test1.SessionID
FROM test1
INNER JOIN 
(
    SELECT SessionID
            MAX(Time) AS MaxTime
    FROM test1
    WHERE ActionName IN ("a", "b")
    GROUP BY SessionID
) sub0
ON test1.SessionID = sub0.SessionID
INNER JOIN U_SessionID 
ON sub0.SessionID = U_SessionID.SessionID
AND sub0.MaxTime = U_SessionID.Time

如果时间不是唯一的,但假设表有一个名为 id 的唯一列:-

SELECT U_SessionID.SessionID, test1.ActionName, test1.SessionID
FROM test1
INNER JOIN  
(
    SELECT SessionID
            SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY Time DESC), ',', 1) AS MaxId
    FROM test1
    WHERE ActionName IN ("a", "b")
    GROUP BY SessionID
) sub0
ON test1.SessionID = sub0.SessionID
INNER JOIN U_SessionID 
ON sub0.SessionID = U_SessionID.SessionID
AND sub0.MaxId = U_SessionID.id

编辑

如果您只想为每个会话 id 随机记录,那么您可以(ab)使用 GROUP BY 子句。我真的不喜欢这个想法,因为虽然它可能确实有效,但根据您的 MySQL 数据库的配置,它可能无法正常工作,即使它确实有效,也可能有人会进行更新以使其停止工作。即使这样,即使它仍然有效,也无法保证它会带回一条真实记录,而不是单行,其列是来自不同行的混合。

为了完整起见,放在这里是为了给你一个选择,但我强烈建议不要使用它

SELECT U_SessionID.SessionID, test1.ActionName, test1.SessionID
FROM test1
INNER JOIN U_SessionID ON U_SessionID.SessionID = test1.SessionID 
WHERE ActionName  IN ("a" , "b")
GROUP BY U_SessionID.SessionID

如果您想要一个更面向未来的简单解决方案,请使用我的第二个解决方案并删除 GROUP_CONCAT 中的 ORDER BY 子句

【讨论】:

感谢您的评论;我想尝试一种更轻松的方法,如我上面的编辑中所述。我会很感激你再看看。谢谢 @Mariah - 添加了更多细节【参考方案2】:

您可以更改查询,如下所示。您的子查询在这里是不必要的。

SELECT U_SessionID.SessionID, test1.ActionName, test1.SessionID
FROM test1
INNER JOIN U_SessionID ON U_SessionID.SessionID = test1.SessionID 
WHERE ActionName  IN ("a" , "b")
ORDER BY `Time` DESC
LIMIT 1;

【讨论】:

感谢您的评论;这也需要很长时间。你能看看我对新方法的编辑吗?

以上是关于创建包含具有条件的唯一行的新表; MySQL的主要内容,如果未能解决你的问题,请参考以下文章

如何在具有某些首字母的新表中插入所有行(pl/sql)

HIVE:使用原始表中特定列的 n 值创建一个包含 n 列的新表

如何在另一个表的大查询中创建一个包含嵌套数据的新表?

MySQL:使用来自查询的信息创建一个新表

将带有数据的新表包含到现有的 Debezium 连接器中

如何将数据集拆分为两个具有唯一和重复行的数据集?