mysql - 具有反向查找的多对多关系

标签 mysql sql many-to-many

MySQL 版本 5.5.35-日志

我有一个非常大的数据集,其中包含与在奥特莱斯购物的人密切相关的多对多关系。一个人可能在数百个不同的商店购物,同样,成千上万的人可能在任何特定商店购物。总人数和网点均达到数百万。

我有一种情况,必须快速解决检查某人是否在特定商店购物的问题,所以我选择使用反向查找;即每个“人”行存储他们购物的商店的 ID 列表。由于数据量大,第三个关系表被认为是不合适的;即每个人的网点都有一排。我在这里的假设是,它别无选择,只能对很多很多行进行表扫描。

然而,要在 MySQL 中存储这种反向查找,SET 也不合适,因为它最多有 64 个条目,这在这种情况下当然是不够的。因此,我选择了一个 BLOB,它的结构只是一个包含每个 4 字节小端 ID 的 block 。

但是,这里出现了一个不同的问题;当需要使用 SQL 查找 BLOB 中是否包含导出 ID 时,异常情况开始发生。从其他问题来看,似乎唯一的方法是在循环中使用 SUBSTRING 和 BLOB,但这似乎不起作用; SUBSTRING 正在返回一个空字符串。首先,这是一些代码:

CREATE FUNCTION `DoesShopAt`(shopperID INT UNSIGNED,outletID TINYBLOB) RETURNS VARCHAR(20)
BEGIN

-- Setup a loop. We're going to loop through each ID in the blob:
declare i_max int unsigned default 0;
declare i int unsigned default 0;
declare offset int unsigned default 0;
declare storeID tinyblob;

-- Setup the blob store - all the stops a particular shopper goes to:
declare allShops blob;

-- Grab the set of ID's - a blob of each 4 byte outlet ID:
select AllStores from Shoppers where ID=shopperID into allShops;

-- How many shops?
select length(allShops)/4 into i_max;

while i < i_max do

    -- Grab the shops ID:
    set storeID=substring(allShops,offset,4);

    if outletID = storeID then
        return "Yep, they do!";
    end if;

    -- Update the ID offset in the blob:
    set offset=offset+4;

    -- Update the loop counter:
    set i=i+1;
end while;

return "Nope, they don't.";
END

出于调试目的,它被设置为返回一个字符串。目的是根据给定的购物者是否在给定的商店购物而返回 true 或 false。

理想情况下,此函数将接收两个数字; shopperID 和 outletID,但是将 outletID 转换为 4 个小端字节的 block 似乎不可靠且充其量也很慢,因为它必须通过十六进制(据我所知)。因此,调用服务改为提供 4 字节的 block 。

有趣的是,在设置后立即返回 storeID 会导致空字符串。如果 storeID 的类型是 varchar、binary 或 tinyblob,就会出现这种情况;似乎无论如何,它都返回一个空字符串。

因此,作为测试目的的最后手段,我尝试了这个:

set storeID=substring(hex(allShops),offset,8);

确保这次偏移量计数器增加了 8,并且调整了输入 ID 以适应。尽管如此,它仍然返回一个空字符串(再次在设置后立即返回 storeID),即使 allShops 数据不为零。

编辑: 虽然我发现了这个问题,但我还是忍不住想也许在 MySQL 中有更好的方法来进行这样的反向查找;你有什么建议吗?

最佳答案

我开始研究子字符串并意识到问题所在;偏移量在应该为 1 时被初始化为 0。更改此设置然后开始正确返回结果:

declare offset int unsigned default 0;

应该是:

declare offset int unsigned default 1;

但是,请参阅原始问题底部的注释。

关于mysql - 具有反向查找的多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21211296/

相关文章:

mysql - 从选择中排除 2 行

mysql - 难以使用 LAG 获取每月进度百分比

sql - InnoDB 表从固定长度的行中获益多少?

ruby-on-rails - ActiveRecord::HasManyThroughAssociationNotFoundError 在 UserController#welcome

hibernate - JPA2 多对多关系上的级联删除

mysql - 更新并加入查询

mysql - 群组通知系统数据库设计

MySQL 从另一个表更新值

sql - django 中的全外连接

java - 如何在 Spring JPA Repository 类的 ManyToMany 产品模式中执行 "findByCategory"?