php find_in_set,php-如何使用IN,FIND_IN_SET比较逗号分隔的字符串中的多个值?

本文介绍了一种在MySQL中避免存储逗号分隔值的复杂查询问题,并提供了更高效的方法,如创建新表存储单个值,以及使用GROUP_CONCAT和用户定义变量实现字符串操作。作者建议遵循第一NF原则,以提高数据结构的清晰度和查询效率。
摘要由CSDN通过智能技术生成

我有多个逗号分隔的值

(1,3,5)要与(2,3,4,5,7,5)比较,此设置引用列值.所以它应该返回3和5

这个值是动态的

我用过

SELECT * FROM table WHERE FIND_IN_SET(‘3’,(‘2,3,4,5,7,5’))AND FIND_IN_SET(‘5’,(‘2,3,4,5,7,5’))等等

但这很麻烦,让我知道任何更好的解决方案.

解决方法:

简短答案

您应该避免这种情况.尽管实际上可以做到,但是您当前的体系结构至少违反了first NF.这是很糟糕的情况.仅在需要使用整个字符串而不是单独的值本身时,才适用存储定界符分隔的列表.因此,最合适的解决方案是:创建其他表并将值放在此处.

长答案

这可以视为某种困惑-但我强烈建议您不要在实际应用中使用它.因此,假设我们有表t:

+------+------------------+

| id | col |

+------+------------------+

| 1 | 1,35,61,12,8 |

| 4 | 82,12,99,100,1,3 |

| 6 | 35,99,1 |

+------+------------------+

我们想将字符串与字符串“ 1、3、35”“相交”.我假设您的字符串是从应用程序派生的-因此,您可以使用它进行一些准备.

最终的SQL将如下所示:

SELECT

resulted.id,

GROUP_CONCAT(resulted.sub) AS result

FROM

(SELECT

r.id,

TRIM(BOTH ',' FROM SUBSTR(

r.col,

@cur,

LOCATE(',', r.col, @cur+1)-@cur

)) AS sub,

@cur:=IF(

CHAR_LENGTH(r.col)=LOCATE(',', r.col, @cur+1),

1,

LOCATE(',', r.col, @cur+1)

) AS cur

FROM

(SELECT

id,

CONCAT(TRIM(BOTH ',' FROM t.col), ',') AS col,

CHAR_LENGTH(

REPLACE(

REPLACE(

REPLACE(

REPLACE(

REPLACE(

REPLACE(

REPLACE(

REPLACE(

REPLACE(

REPLACE(col

, '9', '')

, '8', '')

, '7', '')

, '6', '')

, '5', '')

, '4', '')

, '3', '')

, '2', '')

, '1', '')

, '0', '')

) + 1 AS repeats

FROM t) AS r

LEFT JOIN

(SELECT

(two_1.id + two_2.id + two_4.id +

two_8.id + two_16.id) AS id

FROM

(SELECT 0 AS id UNION ALL SELECT 1 AS id) AS two_1

CROSS JOIN (SELECT 0 id UNION ALL SELECT 2 id) AS two_2

CROSS JOIN (SELECT 0 id UNION ALL SELECT 4 id) AS two_4

CROSS JOIN (SELECT 0 id UNION ALL SELECT 8 id) AS two_8

CROSS JOIN (SELECT 0 id UNION ALL SELECT 16 id) AS two_16

) AS init

ON init.id

CROSS JOIN

(SELECT @cur:=1) AS vars

) AS resulted

INNER JOIN

(SELECT '1' AS sub UNION ALL

SELECT '3' UNION ALL

SELECT '35'

) AS input

ON resulted.sub=input.sub

GROUP BY

resulted.id

(该示例可用于here).

这个怎么运作

此SQL使用了一些技巧.首先,迭代变量. MySQL支持user-defined variables,它们可用于查询中的某种迭代.而且我们正在使用它来将有效的偏移量和长度传递到我们的字符串中,以通过SUBSTR()获得它.

下一个技巧:我们需要产生一定数量的行-否则迭代将无法进行.可以通过以下方式完成:在每一行中对定界符进行计数,并以该计数1重复它.MySQL没有序列,但是还有第三招:通过巨大的CROSS JOIN创建所需的计数(总和为2的幂以得到连续数)数字).这就是内部LEFT JOIN的含义.实际上,我在one中已经遇到了这个问题.

最后,我们对整个结果进行INNER JOIN以获得相交的值.注意:这是部分,您需要为字符串做一些准备.但是在应用程序中拆分字符串很容易,上面需要查询的UNION ALL部分.

出什么问题了

>无效的字符串.不会对“ 1 、、、、、 4、5”之类的内容进行检查.真的-这不是此方法的意图

>无效的非数字值.由于我们要替换0..9(巨大的REPLACE部分)-我们不能动态地做到这一点-MySQL无法“替换任何char,除非..”这是一个瓶颈,是的-但是,再次-不是故意的方法的

标签:sql,mysql,php

来源: https://codeday.me/bug/20191122/2055955.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值