如何使用 in() 函数从 mysql 存储函数返回的值?
Posted
技术标签:
【中文标题】如何使用 in() 函数从 mysql 存储函数返回的值?【英文标题】:How to use values returned from mysql stored function with in() function? 【发布时间】:2011-12-01 12:34:39 【问题描述】:我有一个名为“dealBusinessLocations”的字段(在表“dp_deals”中),其中包含以逗号分隔格式的另一个表(dp_business_locations)的一些 ID。
dealBusinessLocations
----------------------
0,20,21,22,23,24,25,26
我需要在查询的 in() 函数中使用这些值。
喜欢
select * from dp_deals as d left join dp_business_locations as b on(b.businessLocID IN (d.dealBusinessLocations) ;
Sine mysql不支持任何字符串爆炸功能,我创建了一个存储函数
delimiter //
DROP FUNCTION IF EXISTS BusinessList;
create function BusinessList(BusinessIds text) returns text deterministic
BEGIN
declare i int default 0;
declare TmpBid text;
declare result text default '';
set TmpBid = BusinessIds;
WHILE LENGTH(TmpBid) > 0 DO
SET i = LOCATE(',', TmpBid);
IF (i = 0)
THEN SET i = LENGTH(TmpBid) + 1;
END IF;
set result = CONCAT(result,CONCAT('\'',SUBSTRING(TmpBid, 1, i - 1),'\'\,'));
SET TmpBid = SUBSTRING(TmpBid, i + 1, LENGTH(TmpBid));
END WHILE;
IF(LENGTH(result) > 0)
THEN SET result = SUBSTRING(result,1,LENGTH(result)-1);
END IF;
return result;
END//
delimiter ;
该功能运行良好。
mysql> BusinessList( '21,22' )
BusinessList( '21,22' )
-----------------------
'21','22'
但是使用该函数的查询也不起作用。这是查询。
select * from dp_deals as d left join dp_business_locations as b on(b.businessLocID IN (BusinessList(d.dealBusinessLocations)));
我也尝试过对函数参数使用静态值,但没有用
select * from dp_deals as d left join dp_business_locations as b on(b.businessLocID IN (BusinessList('21,22')));
使用函数返回的值似乎有问题。
【问题讨论】:
规范化你的表。在此之前,请使用FIND_IN_SET()
函数。
【参考方案1】:
首先,请阅读:
Is storing a comma separated list in a database column really that bad?
Yes, it is
然后,去规范化你的表格。
现在,如果你真的不能这样做,或者在你正常化之前,请使用 FIND_IN_SET()
函数:
select *
from dp_deals as d
left join dp_business_locations as b
on FIND_IN_SET(b.businessLocID, d.dealBusinessLocations)
然后,再读一遍那篇文章。如果查询速度很慢,或者您对该表有其他问题,那么您就会知道原因:
Is storing a comma separated list in a database column really that bad?
Yes, it is
【讨论】:
数据库中的+1 CSV 是纯粹的邪恶,会把你直接送到地狱。 @Johan - 更糟糕的是,它不会直接下地狱,它会让你走很长的路才能到达那里! 我知道 csv 字段是个大问题,但我无法更改数据库架构。感谢您的帮助【参考方案2】:简单,改用find_in_set()
。
SELECT *
FROM dp_deals as d
LEFT JOIN dp_business_locations as b
ON (FIND_IN_SET(b.businessLocID,d.dealBusinessLocations) > 0);
见:http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set
请注意,如果您放弃 CSV 并摆脱困境,您可以使用简单的连接,例如:
SELECT d.*, GROUP_CONCAT(b.dealBusinessLocation) as locations
FROM dp_deals as d
LEFT JOIN dp_business_location as b
ON (d.dealBusinessLocation = b.businessLocID);
作为奖励,这将更快并且标准化。
【讨论】:
我认为你的 2 个参数的顺序是相反的。 我很担心 csv 问题,但我无法更改数据库设计。 find_in_set() 工作正常。感谢您的帮助【参考方案3】:我认为你的问题是IN()
不希望得到一个包含很多字段的字符串,而是很多字段。
使用您的函数,您将发送它:
WHERE something IN ('\'21\',\'22\''); /* i.e. a single text containing "'21','22'" */
不是预期的
WHERE something IN ('21','22');
【讨论】:
请检查上面发布的函数的输出。 IE。 mysql> BusinessList('21,22') BusinessList('21,22') ------------------------ '21','22'。它返回正确的格式。 @SijoKurian - 您的字符串确实是您想要的格式。但是@Cylindric 的答案试图说明的是它仍然只是一个字符串。它不是数字列表。仅仅因为一个字符串恰好有代表数字和逗号等的字符,它不会成为许多项目的列表,它只是 one 字符串,其中包含所有这些字符。您需要做的是返回一个由 许多 个字符串组成的表,而不仅仅是一个字符串。然后你可以做WHERE x IN (SELECT * FROM function())
正如@Dems 所说,事实并非如此。您需要返回几个字符串或数字,而不是一个看起来像多个数字之间用逗号分隔的字符串。以上是关于如何使用 in() 函数从 mysql 存储函数返回的值?的主要内容,如果未能解决你的问题,请参考以下文章