mysql查询以连接不同表之间存储的uuid

2uluyalo  于 2021-06-25  发布在  Mysql
关注(0)|答案(3)|浏览(527)

我有一个uuid,它存储在一个表中作为人类可读的guid,但在另一个表中它被拆分为高位和低位。如何编写查询以联接uuid上的表?
编辑:表2将只有一个结果与给定的上限和下限位,所以希望效率不应该太可怕,但请考虑到这个问题的答案。

table1.uuid = 'b33ac8a9-ae45-4120-bb6e-7537e271808e'
table2.upper_bits = -5531888561172430560, table2.lower_bits = -4940882858296115058

我需要找回 table2.status 随着 table1.* 哪里 table2.upper_bits + table2.lower_bits = table1.uuid (pseudo where语句)但是我不知道如何为联接求table2的上下值之和,或者如何将table1的uuid转换为联接的位。
谢谢!

prdp8dxp

prdp8dxp1#

这里是@uuerdo解决方案的一个变体,应该更有效(有点像装饰连接取消装饰),但我还没有运行解释来确定:

SELECT t1.*, t2.status
FROM (
  SELECT UUID_TO_BIN(uuid) AS tmpid, *
  FROM table1
) AS t1 INNER JOIN (
  SELECT UUID_TO_BIN(CONCAT(HEX(upper_bits), HEX(lower_bits))) AS tmpid, status
  FROM table2
) AS t2 ON t1.tmpid = t2.tmpid

它可能会占用更多的内存,如果表有很多行和/或表1非常宽,则需要记住这一点。
如果您只需要表1和表2中与单个uuid匹配的记录,则应该只执行两个查询,而不是联接:

SELECT *
FROM table1
WHERE UUID_TO_BIN(uuid) = UUID_TO_BIN(?)

SELECT status
FROM table2
WHERE UUID_TO_BIN(CONCAT(HEX(upper_bits), HEX(lower_bits))) = UUID_TO_BIN(?)

如果 upper_bits 以及 lower_bits 如果已编制索引,这将是查询表2的更好方法:

SET @tmpid = UUID_TO_BIN(?);

SELECT status
FROM table2
WHERE upper_bits = @tmpid >> 64, lower_bits = _binary X'FFFFFFFFFFFFFFFF' & @tmpid

你可以将类似的逻辑应用到我的第一个解决方案中(我认为):

SELECT t1.*, t2.status
FROM (
  SELECT 
    UUID_TO_BIN(uuid) >> 64 AS upper_bits,
    _binary X'FFFFFFFFFFFFFFFF' & UUID_TO_BIN(uuid) AS lower_bits,
    *
  FROM table1
) AS t1 INNER JOIN (
  SELECT upper_bits, lower_bits, status
  FROM table2
) AS t2 ON t1.upper_bits = t2.upper_bits AND t1.lower_bits = t2.lower_bits

这些都没有经过测试,但希望它能给你一些想法来玩。

7gcisfzg

7gcisfzg2#

像这样的事情可能有用。。。但显然效率很低。

SELECT ...
FROM table1 AS t1 
INNER JOIN table2 AS t2 ON REPLACE(t1.uuid, '-', '') 
                         = CONCAT(HEX(t2.upper_bits), HEX(t2.lower_bits))
...

…您可能需要根据排序规则/比较强制使用大写/小写。
我倾向于认为更改数据库结构是“绝对必要的”(以回应您对另一个答案的评论)。为了尽量减少对现有查询和逻辑的影响,您可以将其中一个表更改为具有其他匹配字段,并向表中添加触发器以自动填充/更新新字段;然后执行一次更新以设置所有旧记录的值。
我会先尝试修改t1,因为两个int上的索引可能比一个字符串上的索引“更好”;但我不确定将字符串转换成高位和低位会有多直接。
修改t2会更容易,触发因素会比 SET NEW.uuid = CONCAT(HEX(NEW.upper_bits), HEX(NEW.lower_bits)); …我说“比”多一点,因为触发器最好同时插入 - ,因此连接条件可以消除所有函数的使用。
编辑:我找到了一种在纯sql中计算位的方法:

SELECT @uuid := REPLACE('b33ac8a9-ae45-4120-bb6e-7537e271808e', '-', '') AS uuid
   , -1 * CAST((~CAST(CONV(SUBSTRING(@uuid, 1, 16), 16, 10) AS SIGNED) + 1) AS SIGNED) AS upper_bits
   , -1 * CAST((~CAST(CONV(SUBSTRING(@uuid, 17, 16), 16, 10) AS SIGNED) + 1) AS SIGNED) AS lower_bits
;

您可以在t1的触发器中使用类似的内容,并对新字段使用t1的一次性更新。
…它甚至可能有助于加入:

ON -1 * CAST((~CAST(CONV(SUBSTRING(REPLACE(t1.uuid, '-', ''), 1, 16), 16, 10) AS SIGNED) + 1) AS SIGNED) 
  = t2.upper_bits
AND -1 * CAST((~CAST(CONV(SUBSTRING(REPLACE(t1.uuid, '-', ''), 17, 16), 16, 10) AS SIGNED) + 1) AS SIGNED) 
  = t2.lower_bits

注意:是的,在这两个版本中过度的强制转换似乎是必要的(至少在我测试计算的mysql的旧版本上是如此)

zpqajqem

zpqajqem3#

最简单的方法是将低位和高位与uuid一起存储在表1中。然后将表的低位和高位连接起来。
编辑:如果您只需要一行,并且您确定在另一个表中将有一个匹配的行,那么计算uuid=@uuid,较低的\u位=@lbits &高位=@ubits,然后运行以下命令:

Select t1.*, t2.status  
From  
(select * from table1 where uuid = @uuid)  as t1
Cross join  
(select status from table2 where lower_bits =@lbits and upper_bits= @ubits) as t2;

相关问题