我有多个逗号分隔的值
(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