表task数据
实现功能:
数组:$data =Array ( [0] => 68 [1] => 69 );
receiver字段:储存了多个id以“,”分割
要把task表字段receiver储存的id要是有一个id符合$data数组的某个数据,就把task表对应数据查询出来?怎么实现?
select * from task where receiver like '%,'+id+',%' or receiver like id+',%' or receiver like '%,'+id or receiver = id
如果是mysql find_in_set() 方法了解下
先根据主键ID查出receiver字段 , 然后对receiver字段进行String.split(",") , 得到字符串数组或者集合 , 然后对数组和集合进行遍历 , 得到receiver下的各个ID
. 然后用参数和各个ID比对 , 如果能匹配上 , 就把该记录查出来 . 不知道我说的够不够明白
取出非空的receiver用split分解字段的到数组再比较不就得了
1、查询所有非空的receiver,放到一个字符串数组中,每个字符串是逗号分隔的id
2、逐个遍历$data 的每项看是否在查询出的receiver字符串数组中,如果找到了就退出循环,这样就可以找出想要的数据
select * from tablename
where FIND_IN_SET(1, receiver)
FIND_IN_SET这个方法可以,如果是mysql的话。
再加上mybatis 你用foreach和这个函数就可以做到了
遍历数组,生成FIND_IN_SET(1, receiver) or FIND_IN_SET(2, receiver) 就行了
DROP FUNCTION IF EXISTS `find_in_myset`;
CREATE DEFINER = `root`@`%` FUNCTION `find_in_myset`(src varchar(100),dest varchar(100))
RETURNS tinyint(1)
BEGIN
set @i = length(src) - length(replace(src, ',', ''));
set @left_str = src;
while @i>0
do
set @sub_str = substr(@left_str, 1, instr(@left_str, ',') - 1);
set @left_str = substr(@left_str, length(@sub_str) + length(',') + 1);
if FIND_IN_SET(trim(@sub_str), dest) then return 1;
end if;
end while;
RETURN 0;
END;
拿去试试看
DROP FUNCTION IF EXISTS `find_in_myset`;
CREATE DEFINER = `root`@`%` FUNCTION `find_in_myset`(src varchar(100),dest varchar(100))
RETURNS tinyint(1)
BEGIN
set @i = length(src) - length(replace(src, ',', ''));
set @left_str = src;
while @i>0 do
set @i = @i - 1;
set @sub_str = substr(@left_str, 1, instr(@left_str, ',') - 1);
set @left_str = substr(@left_str, length(@sub_str) + 2);
if FIND_IN_SET(trim(@sub_str), dest) then return 1;
end if;
end while;
if FIND_IN_SET(trim(@left_str), dest) then return 1;
else return 0;
end if;
END;
select 1 from dual where find_in_myset('7', '1,2,3,4,5,6')
其实可以用select * from A where ID IN('67,68,69') .给、如果id为67会出这条信息,68也会。69同理
这是一个通用函数,用来截取分割出来的自串
CREATE OR REPLACE TYPE ty_str_split IS TABLE OF VARCHAR2 (4000);
CREATE OR REPLACE FUNCTION fn_split (p_str IN VARCHAR2, p_delimiter IN VARCHAR2)
RETURN ty_str_split PIPELINED
IS
j INT := 0;
i INT := 1;
len INT := 0;
len1 INT := 0;
str VARCHAR2 (4000);
BEGIN
len := LENGTH (p_str);
len1 := LENGTH (p_delimiter);
WHILE j < len
LOOP
j := INSTR (p_str, p_delimiter, i);
IF j = 0
THEN
j := len;
str := SUBSTR (p_str, i);
PIPE ROW (str);
IF i >= len
THEN
EXIT;
END IF;
ELSE
str := SUBSTR (p_str, i, j - i);
i := j + len1;
PIPE ROW (str);
END IF;
END LOOP;
RETURN;
END fn_split;
/
测试:SELECT * FROM TABLE (fn_split ('1;;12;;123;;1234;;12345', ';;'));
结果:
1
12
123
1234
12345
然后...应该知道了吧
SELECT
f.*, u.user_gender,
u.user_name,
u.mobile_phone
FROM
tb_sxd_police_indoor_task f
LEFT JOIN tb_sxd_user u ON u.user_id = f.sponsor
WHERE
exists (
SELECT
1
FROM
tb_police p
WHERE
p.provinceid = 440000
FIND_IN_SET(p.pid, f.receiver)
)
你之前用的连接方式导致数据量增大,其实t表完全不必引用到from后面,改成这样速度应该能快一点。
我个人猜测你是用不到pid的,如果你一定要用pid的话,可以再写一个子查询
SELECT
f.*, u.user_gender,
u.user_name,
u.mobile_phone,
(SELECT
id
FROM
tb_police p
WHERE
p.provinceid = 440000) pid
FROM
tb_sxd_police_indoor_task f
LEFT JOIN tb_sxd_user u ON u.user_id = f.sponsor
WHERE
exists (
SELECT
1
FROM
tb_police p
WHERE
p.provinceid = 440000
FIND_IN_SET(p.pid, f.receiver)
)
我是觉得这个pid都一模一样的,应该没有查询出来的必要吧