与反向查找的多对多关系

时间:2014-01-18 23:38:28

标签: mysql sql many-to-many

MySQL版本5.5.35-log

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

我的情况是检查一个人在特定商店购物是否必须快速解决,所以我选择使用反向查询;即,每个“人”行存储他们所购商店的ID列表。由于数据量大,第三关系表被认为是不合适的;即每个人出口有一排的人。我的假设是,除了通过许多行产生表扫描之外别无选择。

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

但是,这里出现了另一个问题;当需要使用SQL查找BLOB中是否包含插座ID时,会发生异常事件。从其他问题来看,似乎唯一的方法是在循环中使用带有BLOB的SUBSTRING,但这似乎不起作用; 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

出于调试目的,它被设置为返回一个字符串。意图是它返回真或假,取决于给定的购物者是否在给定的商店购物。

理想情况下,此功能会收到两个数字; shopperID和outletID,但是将outletID转换为4个小端字节的块似乎是不可靠的,并且最好是缓慢的,因为它必须通过十六进制(据我所知)。因此,调用服务提供了4个字节的块。

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

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

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

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

编辑:虽然我发现了这个问题,但我不禁想到,在MySQL中可能有更好的方法来反向查找这样的查找;你有什么建议吗?

1 个答案:

答案 0 :(得分:1)

我开始玩子串,并意识到问题所在;当offset应该为1时,偏移量被初始化为0.更改此值然后开始正确返回结果:

declare offset int unsigned default 0;

应该是:

declare offset int unsigned default 1;

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