复选框选中查询的问题

Dragon_pan 2009-09-01 08:31:58
加精
有 设施: □电梯 □空调 □洗衣机 □热水器 □宽带
类似这种复选框多选的问题,数据库的字段该怎么设计,我现在是想用逗号隔开的数字来存储的,但是有个问题是查询的时候怎么做,比如查询时我选中了其中的 □电梯 □空调 □洗衣机这三个,那么如何把有这三个的数据全部查询出来。
不知道这种查询的效率高不高。有没有其他设计的方式、查询又该如何处理呢。因为到时候数据会比较大,如果按我这样的设计就用不上索引了。
模拟一个数据
id result
1 1,2,4
2 2,4,5
3 3,4,5
4 1,3,5
5 2,3,4

当查询1,2,3 时肯定没有,当查询3,5时返回 id为 3和4
不知道这样描述够不够清楚。
...全文
1239 85 打赏 收藏 转发到动态 举报
写回复
用AI写文章
85 条回复
切换为时间正序
请发表友善的回复…
发表回复
axinxkx 2009-09-05
  • 打赏
  • 举报
回复
75楼的说得对,素数用在这个问题上不是最好的办法,如果在16种选择或者32种选择之内的话,用49楼的 位操作是不错的选择。

比如星期,一个Byte就能解决。
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 jiangshun 的回复:]
SQL code--> 测试数据:[TB]ifobject_id('[TB]')isnotnulldroptable[TB]createtable[TB]([id]int,[result]varchar(5))insert[TB]select1,'1,2,4'unionallselect2,'2,4,5'unionallselect3,'3,4,5'unionallselect4,'1,3,5'u¡­
[/Quote]
正解,
JAMJIA 2009-09-04
  • 打赏
  • 举报
回复
路过。。。。。。。。。
longtenggdf 2009-09-04
  • 打赏
  • 举报
回复
就算要满足你提的这个要求也是很容易做到的
“比如查询时我选中了其中的 □电梯 □空调 □洗衣机这三个,那么如何把有这三个的数据全部查询出来。 ”

用 2 3 4 对应的素数分开除就好了。
longtenggdf 2009-09-04
  • 打赏
  • 举报
回复
[Quote=引用 75 楼 fcuandy 的回复:]
逗号分隔,效率是比较差,能不能用,要看你的数据量。

一般推荐的作法,还是分行存储。

至于22楼沟沟的做法,思路很好,但不符合题意。
“比如查询时我选中了其中的 □电梯 □空调 □洗衣机这三个,那么如何把有这三个的数据全部查询出来。 ”

这个逻辑是指,只要含有三个中的一个,就查出来,而22楼的作法,必须全包含 。

比如
1      1,2,4  ==> 2*3*7  =42
2      2,4,5  ==> 3*7*11 =231
3      3,4,5  ==> 5*7*11 =385
4      1,3,5  ==> 2*5*11 =110
5      2,3,4  ==> 3*5*7  =105

我现在要查的是 2,3,4
那么,实际上, 1,2,3,4,5都应该被查出来,但只能查到5.
[/Quote]
他这样是没问题的吧。题目就是这样要求的!
longtenggdf 2009-09-04
  • 打赏
  • 举报
回复
[Quote=引用 78 楼 sohighthesky 的回复:]
引用 65 楼 changhai_yu 的回复:
关系数据库设计的第一范式,字段不可再分。数据库设计阶段就出了问题,解决起来当然费劲。
最直接的方法是建一个关系表,其中一个字段来存储选中的值,选中多个是多条记录,没选中,就没有关联记录。这样的设计直观、易懂,处理起来也方便!

没选中也要有记录才好,要不然,修改的时候就还要判断是insert 还是update了
[/Quote]
没有update的。修改分两种情况吧。勾选之前没选的和取消已选择的。前面是insert,后面是delete.
topest0302 2009-09-04
  • 打赏
  • 举报
回复
建议分行存储比较好
xiaoliaoyun 2009-09-04
  • 打赏
  • 举报
回复
可以用XML类型.查询的时候也可以使用索引.
华夏小卒 2009-09-04
  • 打赏
  • 举报
回复

declare @tb table(id int, result int)
insert @tb
select
1 , 1 union all select
1 , 2 union all select
2 , 2 union all select
3 , 3 union all select
4 , 1 union all select
4 ,2 union all select
4 ,3

declare @str varchar(10)
set @str='1,2'

select id from @tb
where charindex(','+ltrim(result)+',',','+@str+',')>0
group by id
having(count(*)>1) --这边是大于1


id
-----------
1
4

(2 行受影响)


华夏小卒 2009-09-04
  • 打赏
  • 举报
回复

declare @str varchar(10)
set @str='1,2'

select id from tb
where charindex(','+result+',',','+@str+',')>
group by id
having(count(*)>0)
Dragon_pan 2009-09-04
  • 打赏
  • 举报
回复
[Quote=引用 75 楼 fcuandy 的回复:]
逗号分隔,效率是比较差,能不能用,要看你的数据量。

一般推荐的作法,还是分行存储。

[/Quote]
你说的分行是不是指下面这种形式:
id result
1 1
1 2
2 2
3 3
4 1
4 2
4 3

如果是这样的话,怎么写查询语句得到结果,比如上面的 "1,2",查出的结果就是 1,4这两条
jiangqinggao 2009-09-03
  • 打赏
  • 举报
回复
看看,。
sohighthesky 2009-09-03
  • 打赏
  • 举报
回复
[Quote=引用 65 楼 changhai_yu 的回复:]
关系数据库设计的第一范式,字段不可再分。数据库设计阶段就出了问题,解决起来当然费劲。
最直接的方法是建一个关系表,其中一个字段来存储选中的值,选中多个是多条记录,没选中,就没有关联记录。这样的设计直观、易懂,处理起来也方便!
[/Quote]
没选中也要有记录才好,要不然,修改的时候就还要判断是insert 还是update了
xbbox 2009-09-03
  • 打赏
  • 举报
回复
高手很多,学习了
lianda220 2009-09-03
  • 打赏
  • 举报
回复
我处理过一次这个问题,当时吧我是吧复选框的内容存在数据库的一个字段,用"|"隔开,然后在查出来的时候是在前台用JS处理的,具体的方法如下:
window.onload = function()
{
dochaiyy(); //加载页面复选框值

}
function dochaiyy() {
var tl = document.getElementById("haveFunction").value;

if (tl!= null&&tl.length!=0) {
var tls = new Array();
tls=tl.split("|");
for (var i = 0; i < tls.length; i++)
{
for (var n = 0; n < document.all.tl.length; n++) {
if (document.all.tl[n].value==tls[i]) {
document.all.tl[n].checked=true;
}
}
}
}
}
fcuandy 2009-09-03
  • 打赏
  • 举报
回复
逗号分隔,效率是比较差,能不能用,要看你的数据量。

一般推荐的作法,还是分行存储。

至于22楼沟沟的做法,思路很好,但不符合题意。
“比如查询时我选中了其中的 □电梯 □空调 □洗衣机这三个,那么如何把有这三个的数据全部查询出来。 ”

这个逻辑是指,只要含有三个中的一个,就查出来,而22楼的作法,必须全包含 。

比如
1 1,2,4 ==> 2*3*7 =42
2 2,4,5 ==> 3*7*11 =231
3 3,4,5 ==> 5*7*11 =385
4 1,3,5 ==> 2*5*11 =110
5 2,3,4 ==> 3*5*7 =105

我现在要查的是 2,3,4
那么,实际上, 1,2,3,4,5都应该被查出来,但只能查到5.
skydogdragon 2009-09-03
  • 打赏
  • 举报
回复
拆分表,那修改的时候可就麻烦了,需要涉及到增删了
遛乌龟 2009-09-03
  • 打赏
  • 举报
回复
[Quote=引用 71 楼 xueyuan299 的回复:]
我觉得LZ将“设施”做为一个单独的表比较好,在数据量大时还可减少数据冗余,做为字段不合适。查询时采用关联查询,效率应该不差。
[/Quote]

和我想的一样儿o(∩_∩)o
T表:tableName=t_table, 设施表:tableName=t_device
在T表的model中设计成:
private Set<TDevice> device;
表结构:
t_table_id,column1,column2,...,t_device_id;



这样儿设计的话就没有那么繁琐了、、、
deepiheart 2009-09-03
  • 打赏
  • 举报
回复
id result
1 1,2,4
2 2,4,5
3 3,4,5
4 1,3,5
5 2,3,4

设计成这样
id result
1 11010
2 01011
3 00111
4 10101
5 01110

0代表没选1代表对应设备选了
当查询1,2,3 时:
select * from 表 where result like '111__';
当查询3,5时:
select * from 表 where result like '__1_1';
xueyuan299 2009-09-03
  • 打赏
  • 举报
回复
我觉得LZ将“设施”做为一个单独的表比较好,在数据量大时还可减少数据冗余,做为字段不合适。查询时采用关联查询,效率应该不差。
加载更多回复(65)

22,210

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧