FIND_IN_SET()vs IN()

我有两个表在我的数据库。 一个是订单,一个是公司。

订单有这样的结构:

OrderID | attachedCompanyIDs ------------------------------------ 1 1,2,3 2 2,4 

公司有这样的结构:

 CompanyID | name -------------------------------------- 1 Company 1 2 Another Company 3 StackOverflow 4 Nothing 

要获取订单的公司名称,我可以这样查询:

 SELECT name FROM orders,company WHERE orderID = 1 AND FIND_IN_SET(companyID, attachedCompanyIDs) 

该查询工作正常,但以下查询不。

 SELECT name FROM orders,company WHERE orderID = 1 AND companyID IN (attachedCompanyIDs) 

为什么第一个查询工作,而不是第二个?

第一个查询返回:

 name --------------- Company 1 Another Company StackOverflow 

第二个查询只返回:

 name --------------- Company 1 

为什么这是为什么第一个查询返回所有的公司,但第二个查询只返回第一个查询?

 SELECT name FROM orders,company WHERE orderID = 1 AND companyID IN (attachedCompanyIDs) 

attachedCompanyIDs是投入INTcompanyID类型)的标量值。

演员只返回数字,直到第一个非数字(在你的情况下逗号)。

从而,

 companyID IN ('1,2,3') ≡ companyID IN (CAST('1,2,3' AS INT)) ≡ companyID IN (1) 

PostgreSQL ,您可以将字符串转换为数组(或者将其存储为数组):

 SELECT name FROM orders JOIN company ON companyID = ANY (('{' | attachedCompanyIDs | '}')::INT[]) WHERE orderID = 1 

这甚至会在companyID上使用索引。

不幸的是,这在MySQL不起作用,因为后者不支持数组。

你可能会觉得这篇文章很有趣(见#2 ):

  • MySQL中的10件事情(这不会按预期工作)

更新:

如果在逗号分隔列表中的值的数量有一些合理的限制(比如不超过5 ),那么你可以尝试使用这个查询:

 SELECT name FROM orders CROSS JOIN ( SELECT 1 AS pos UNION ALL SELECT 2 AS pos UNION ALL SELECT 3 AS pos UNION ALL SELECT 4 AS pos UNION ALL SELECT 5 AS pos ) q JOIN company ON companyID = CAST(NULLIF(SUBSTRING_INDEX(attachedCompanyIDs, ',', -pos), SUBSTRING_INDEX(attachedCompanyIDs, ',', 1 - pos)) AS UNSIGNED) 

attachedCompanyIDs是一个大字符串,所以mysql试图在这里找到公司,把它转换成整数

当你在哪里使用

所以如果comapnyid = 1:

 companyID IN ('1,2,3') 

这是真的

但是如果数字1不在第一位

  companyID IN ('2,3,1') 

其返回错误

要获得所有相关的公司名称,不要根据特定的ID。

 SELECT (SELECT GROUP_CONCAT(cmp.cmpny_name) FROM company cmp WHERE FIND_IN_SET(cmp.CompanyID, odr.attachedCompanyIDs) ) AS COMPANIES FROM orders odr 

由于第二个查询正在查找ID为1或2或3的行,因此第一个查询正在查找companyID中存在的逗号分隔值之一,

这里的另一个问题是你没有加入一个共同的关键在你的位置,所以你会得到= count(table1)* count(table2)行的突变;

你的问题真的存在于我的答案的第二部分。 (用你的第二个查询)

让我来解释何时使用FIND_IN_SET和何时使用IN。

我们来看一个名为“aid”,“aname”的列表。 我们来看一下名为“bid”,“bname”,“aids”的列表B。

现在在表A和表B中有如下的虚拟值。

表A

援助aname

1苹果

2香蕉

3芒果

表B

投标bname艾滋病

1苹果1,2

2香蕉2,1

3芒果3,1,2

 enter code here 

情况1:如果你想从表b中得到这些记录,这些记录在艾滋病列中有1个值,那么你必须使用FIND_IN_SET。

查询:select * from A JOIN B ON FIND_IN_SET(A.aid,b.aids)where A.aid = 1;

情况2:如果你想从表格a中获得那些1或2或3的数值出现在援助栏中的记录,那么你必须使用IN。

查询:select * from A JOIN B ON A.aid IN(b.aids);

现在在这里,你通过mysql查询你需要什么。

 SELECT o.*, GROUP_CONCAT(c.name) FROM Orders AS o , Company.c WHERE FIND_IN_SET(c.CompanyID , o.attachedCompanyIDs) GROUP BY o.attachedCompanyIDs