4

我有两张桌子:category(cat_id type int,cat_name)books(book_id type int,cat_id)。当我将一本书分配给用户时,他将获得一个book code. 我想形成包含 12 个字母数字字符的本书代码,它必须源自cat_idand book_id。此外,我应该能够解码代码以获得cat_idand book_id。任何想法?。

4

3 回答 3

3

使用 HEX 有一种更简单的方法,但您需要决定书籍使用多少位数以及类别使用多少位数。

例如,我建议将 8 用于书籍,将 4 用于类似的类别。通过使用十六进制一,最大记录为 FFFFFFFF FFFF,您可以在其中用完所有无符号整数的书籍(最多 4294967295 本书)和 65535 个类别。

实际上,LPAD(HEX(book_id), 8, '0')对于前 8 位数字和LPAD(HEX(cat_id), 4, '0')后 4 位数字。

所以你想要的书代码可以通过SELECT CONCAT(LPAD(HEX(book_id), 8, '0'),LPAD(HEX(cat_id), 4, '0')) FROM books

要取回: SELECT UNHEX(substr(code,1,8)) as book_id, UNHEX(substr(code,9,4)) as cat_id FROM bookcode WHERE id=1

如果您想在书籍代码中包含更大的数据集,您可以尝试对这两个项目使用 base36 甚至 base62(区分大小写)编码。这种编码需要您自己的用户程序代码。

于 2013-04-25T09:48:32.550 回答
2

好的,给你...

这可以处理最大有符号整数类型。并且产生不超过 12 个字符。

$firstId = "2147483646";
$secondId = "2147483646";
$firstBinary  = str_pad(base_convert($firstId, 10, 2), 31, "0", STR_PAD_LEFT);
$secondBinary  = str_pad(base_convert($secondId, 10, 2), 31, "0", STR_PAD_LEFT);
$finalBase36 = str_pad(base_convert($firstBinary.$secondBinary, 2, 36), 12, "0", STR_PAD_LEFT);
var_dump($finalBase36);

更新:对不起,我犯了一个错误..这应该用更新的代码来解决问题。

于 2013-04-25T09:59:51.997 回答
0

假设int类型是 32 位无符号整数。2int组合将有 2^64 个唯一值,大约为 1.844e19。

如果我们只使用小写或大写英文字母加数字,则有 36^12 = 4.738e18 个不同的值,这不足以创建从 2 个键到书码的一对一映射。

如果您在图书代码的字符集中再添加 5 个字符,则将有 41^12 = 2.256e19 个不同的值,这足以创建一对一映射。

但是,转换将涉及除法和乘法,当您从书本代码转换回键时,可能会发生整数溢出。

如果可能,您可能希望将字符集扩展到 64 个字符:26 * 2 小写/大写英文字母、10 个数字和 2 个特殊字符(可能是_-),您可以在其中玩位移位 - 这是安全的整数溢出。对于未使用的位,您可能希望用随机数据填充它,这些数据由 2 个密钥播种;反向构造将忽略具有随机位的(固定)位置。

于 2013-04-25T09:49:52.783 回答