合并 mariadb 中的 n 个表并根据时间戳找到不同的值

Union n amount of tables in mariadb and find the distinct value based on timestamp

我需要在多个数据库 table 上进行搜索。由于所有 table 都具有相同的结构(相同的列,它们实际上是相同 table 的存档数据)我可以使用 UNION ALL 将它们全部组合起来。

但是,挑战是我需要为用户名列获取不同的值,并且在对所有存档数据使用 UNION ALL 之后,我需要为每个用户名值找到最早的 Time_stamp。

我浏览了文档并在谷歌上搜索了很长一段时间,但没有找到令人满意的解决方案 MySQL。

我能想到的唯一方法是编写一些外部代码来为每个用户名使用 UNION ALL 搜索值。并且 运行 1 乘 1 查询。知道我在数据库中列出了 100k 个不同的用户名,这将花费相当长的时间。这个脚本我已经启动了,但是感觉效率很低,很浪费资源。

SELECT * FROM table1 WHERE `USERNAME` LIKE 'USERNAMEXXX'
UNION ALL
SELECT * FROM table2 WHERE `USERNAME` LIKE 'USERNAMEXXX'
UNION ALL
SELECT * FROM table3 WHERE `USERNAME` LIKE 'USERNAMEXXX'
UNION ALL
SELECT * FROM table4 WHERE `USERNAME` LIKE 'USERNAMEXXX'
ORDER BY TIME_STAMP ASC
LIMIT 1

上面的 SQL 查询为我提供了我想要的每个用户名,但我需要为每个不同的用户名重复它。

补充一下,我还有另一个 table,它包含所有不同的用户名值。我使用 table 来填充对我的外部代码解决方案的搜索。

有没有什么方法可以使用本机 SQL 实现此目的,而无需外部脚本?将 distinct、union all 和 order by timestamp asc limit 1.

组合在一起的东西

如果我没看错你的问题

您可以将 min 用于最早的时间戳 min(my_time_stamp) 和 UNION(对于 return distinct )

select  username, min(my_time_stamp)
from  table1 
group  by username 
union  
select  username, min(my_time_stamp)
from  table2 
group  by username 
union
select  username, min(my_time_stamp)
from  table3 
group  by username 
....

union
select  username, min(my_time_stamp)
from  tableN
group  by username 

order by username  

在MySQL 8+中,您可以使用window函数:

SELECT t.*
FROM (SELECT t.*,
             ROW_NUMBER() OVER (PARTITION BY username ORDER BY timestamp) as seqnum
      FROM ((SELECT t.* FROM table1 t) UNION ALL
            (SELECT t.* FROM table2 t) UNION ALL
            (SELECT t.* FROM table3 t) UNION ALL
            (SELECT t.* FROM table4 t)
           ) t
     ) t
WHERE seqnum = 1;

在早期版本中,您可以使用变量:

SELECT t.*
FROM (SELECT t.*,
             (@rn := IF(@u = username, @rn + 1,
                        IF(@u := username, 1, 1)
                       )
             ) as seqnum
             ROW_NUMBER() OVER (PARTITION BY username ORDER BY timestamp) as seqnum
      FROM ((SELECT t.* FROM table1 t) UNION ALL
            (SELECT t.* FROM table2 t) UNION ALL
            (SELECT t.* FROM table3 t) UNION ALL
            (SELECT t.* FROM table4 t)
            ORDER BY username, timestamp
           ) t CROSS JOIN
           (SELECT @u := '', @rn := 0) params
     ) t
WHERE seqnum = 1;

以上假定您需要所有列。如果您只想要最小时间戳和用户名,请使用聚合:

SELECT username, MIN(timestamp),
FROM ((SELECT t.* FROM table1 t) UNION ALL
      (SELECT t.* FROM table2 t) UNION ALL
      (SELECT t.* FROM table3 t) UNION ALL
      (SELECT t.* FROM table4 t)
     ) t
GROUP BY username;