我有个这样的数据表, articles下面是文章id号码 (mysql数据库)
要求结果:根据给定的文章id号 查出 id values比如 articles给出的是 5 那么结果应该是 第一行and第三行 id values articles
1 aaa 1-2,4-9,37
2 bbb 23,80
3 ccc 1-24
要求结果:根据给定的文章id号 查出 id values比如 articles给出的是 5 那么结果应该是 第一行and第三行 id values articles
1 aaa 1-2,4-9,37
2 bbb 23,80
3 ccc 1-24
解决方案 »
- 超市mysql 服务器与客户端问题
- 向:haihun666 提问。。不同的数据库文件保存到不同的物理位置下
- 如何用sql删除冗余整行都有冗余的记录(全部字段)
- 求.net用PgOleDB连接PostgreSql的例子.
- mysql date_format()函数问题。。。
- 求mysql中的查询语句?
- 如何将MSSQL2000的存储过程转换成为postgreSQL的函数???
- 怎样访问远程数据库?
- 奇怪!最近在做一個vb+MySQL的程序,其中有一个sql语句是统计所查询的金额,计算的值不对??!详细请看...
- 【求进】MySQL 5.7+如何Where查找JSON数组内对象的值
- 求这样的SQL语句
- 我有一个城市的数据表,里面包括中文名和英文名!
1 aaa 1-2,4-9,371 aaa 1
1 aaa 2
1 aaa 4
...............
1 aaa 9这样查询很简单,否则同样要拆分字符串,以,为分隔,取-前后字段内容,再做比较
如果仅限于用SQL语句则很难实现。毕竟这个atricles 字段并不属数据库的范式要求(连1NF都无法满足。)基于现在这个设计,大家一起看看程序中有什么好的算法。
+----+-------+------------+
| id | value | articles |
+----+-------+------------+
| 1 | aaa | 1-2,4-9,37 |
| 2 | bbb | 23,80 |
| 3 | ccc | 1-24 |
+----+-------+------------+
3 rows in set (0.00 sec)
mysql> select * from text t where id in (select substring(articles,1,instr(arti
cles,",")-1) from t);
+----+-------+------------+
| id | value | articles |
+----+-------+------------+
| 1 | aaa | 1-2,4-9,37 |
+----+-------+------------+
1 row in set (0.00 sec)
这个查询之简单匹配 通过拆分字符串 第一个“,”前的字符 ,即id=1 1在“ 1-2,4-9,37 ”存在但是要满足你想要的需求要做大量的sql语句
需要存储过程实现 但是还是建议2楼说的 你表设计有问题
函数内部根据“,”和“-”来判断处理就可以了,若存在的,函数返回1,否则返回0
SELECT newb,a1.values,
IF(INSTR(newb,'-')>0,LEFT(newb,INSTR(newb,'-')-1),newb) AS mi,
IF(INSTR(newb,'-')>0,MID(newb,INSTR(newb,'-')+1,LENGTH(newb)),newb) AS ma
FROM (
SELECT a.*,
MID(MID(newa,b.id,LENGTH(newa)),2,LOCATE(',',MID(newa,b.id,LENGTH(newa)),2)-2) AS newb
FROM (
SELECT *,CONCAT(',',articles,',') AS newa FROM `test`.tn) a,lsb2 b
WHERE LENGTH(newa)>=b.id
AND MID(newa,b.id,1)=','
AND LENGTH(MID(newa,b.id,LENGTH(newa)))>=2
ORDER BY a.values,b.id) a1 ) a2
WHERE 5 BETWEEN mi AND ma
其中LSB2只有ID字段,内容1-1000数字,`test`.tn为工作表
不知道你的操作语言是什么,来个类似于C的伪代码好了:
for(id=第一个,id<=最后一个,id++)
{//不遍历是不行的字符串 strArt=该行articles 。
//when i=1,strArt=1-2,4-9,37 //第1种可能:目标编号==37
将目标编号转换为字符串,在strArt中查找
,如果有就是找到了,将该id加入结果。//第2种可能:目标编号==7
for(从strArt第一个字符到最后一个循环,设当前的字符为c)
{
if(c==‘-’)
{
以(字符串前边界,字符串后边界,逗号)为边界,
取c前后的字符,将这个字符串转换为int型得到iBef,iAft。
if(目标编号>iBef and 目标编号<iAft)
{
找到了!将该id加入结果
}
}}
for(i=id第一个,i<=id最后一个,id++)
{//不遍历是不行的 字符串 strArt=该行articles 。
//when i=1,strArt=1-2,4-9,37 //第1种可能:目标编号==37
将目标编号转换为字符串,在strArt中查找
,如果有就是找到了,将该id加入结果。 //第2种可能:目标编号==7
for(从strArt第一个字符到最后一个循环,设当前的字符为c)
{
if(c==‘-’)
{
以(字符串前边界,字符串后边界,逗号)为边界,
取c前后的字符,将这个字符串转换为int型得到iBef,iAft。
if(目标编号>iBef and 目标编号<iAft)
{
找到了!将该id加入结果
}
} }
}
1 aaa 1-2,4-9,37
这个设计数据库的该打PP连第一泛式,1NF,原子不可分性都不遵守!~~
用两个函数,一个存储过程可以做出来!函数一:func_get_split_string
CREATE FUNCTION `func_get_split_string`(
f_string varchar(1000),f_delimiter varchar(5),f_order int) RETURNS varchar(255) CHARSET utf8
BEGIN
declare result varchar(255) default '';
set result = reverse(substring_index(reverse(substring_index(f_string,f_delimiter,f_order)),f_delimiter,1));
return result;
END函数二:func_get_split_string_total
CREATE FUNCTION `func_get_split_string_total`(
f_string varchar(1000),f_delimiter varchar(5)
) RETURNS int(11)
BEGIN
return 1+(length(f_string) - length(replace(f_string,f_delimiter,'')));
END存储过程一:
CREATE PROCEDURE `useCursor`(in articleId int)
BEGIN
declare tmpId int;
declare tmpArticles varchar(255) default '' ;
declare allId varchar(255) default '' ;
declare allArticles varchar(255) default '' ;
declare i INT DEFAULT 0;
declare j INT DEFAULT 0;
declare i_count int;
declare j_count int;
declare beginNum int;
declare endNum int;
declare sSql varchar(4000);
declare cur1 CURSOR FOR SELECT id,articles FROM a1;
declare CONTINUE HANDLER FOR SQLSTATE '02000' SET tmpId = null; set sSql = 'select * from a1 where';
OPEN cur1;
FETCH cur1 INTO tmpId,allArticles;
WHILE (tmpId is not null) DO
SELECT func_get_split_string_total(allArticles,',') into i_count;
set i = 0;
while i < i_count do
set i = i + 1;
select func_get_split_string(allArticles,',',i) into tmpArticles;
SELECT func_get_split_string_total(tmpArticles,'-') into j_count;
if (j_count =1) then
select func_get_split_string(tmpArticles,'-',1) into beginNum;
if (beginNum = articleId) then
set allId = CONCAT(allId ,tmpId,',') ;
set sSql = CONCAT(sSql,' id = ',tmpId,' or');
end if;
end if;
if (j_count = 2) then
select func_get_split_string(tmpArticles,'-',1) into beginNum;
select func_get_split_string(tmpArticles,'-',2) into endNum;
if (articleId >= beginNum and articleId <= endNum) then
set allId = CONCAT(allId ,tmpId,',') ;
set sSql = CONCAT(sSql,' id = ',tmpId,' or');
end if;
end if;
end while;
FETCH cur1 INTO tmpId,allArticles;
END WHILE;
CLOSE cur1;
if (length(allId) > 0) then
set sSql = substring(sSql,1,length(sSql)-2);
end if;
set @sQuery = sSql;
prepare stmt from @sQuery;
execute stmt;
END