postgresql:表中有个状态字段integet类型的,用于表示转换为bit(8)后的0、1状态。
例如1转换成00000001后,最后一位1表示某一个状态,0就表示没有某状态。
这8个状态分别用十进制的0,1,2,4...表示,已经在java中定义成常量了。
前台查询这个表时,传入多个状态,包含其中一个或者多个状态的数据都要查出来。
该怎么传数据、写SQL...
不知道说的清楚不?
如果前台传入一个3就是 00000011,表示把存在后两个状态其一或者全部的都查出来。但在sql里怎么进行判断呢?
后者前台不传入3而是其他结构的特定数据/?? 没想到好的办法,
传什么样的数据 ,还有SQL怎么写??? 哪位有经验的给个思路。后者给个sql。
thanks!!!
[b]问题补充:[/b]
我也试过这样开些动态sql但是,并不是所有参数都像3一样查询出1、2、3、
下面是一个列表,我没发现规律,
查询条件 符合条件的............................
1 0001 0001(1)
2 0010 0010(2)
3 0011 0001(1) 0010(2) 0011(3)
4 0100 0100(4)
5 0101 0001(1) 0100(4) 0101(5)
6 0110 0010 (2) 0100(4) 0110(6)
7 0111 0001(1) 0010(2) 0100(4) 0011(3) 0101(5) 0110(6) 0111(7)
8 1000 1000(8)
9 1001 0001(1) 1000(8) 1001(9)
直接: for(int i=1;i<=9;i++){
}
肯定是不对的。。。咋办??
[b]问题补充:[/b]
谢谢yourgame、playfish的回答。也给我思路。
playfish最后给出的结果还只是一个子集,没有组合结果。
我自己写了个方法,实验下好像没问题,但是还是感觉太麻烦,还是这东西本来就很麻烦?sql几个or下来估计很慢。。。
[code="java"]
static String returnZeros(int n){
StringBuffer bf = new StringBuffer();
for(int i=0;i<n;i++){
bf.append("0");
}
return bf.toString();
}
static List<String> getRelust(int state){
List<String> list = new ArrayList<String>();//存放转化后的结果
List<Integer> indexs = new ArrayList<Integer>();//存放二进制字符串转换成char[]后是1的数组下标
String stateStr = Integer.toBinaryString(state);//将状态转换成二进制字符串
stateStr = returnZeros(8-stateStr.length())+stateStr;//不够8位的补齐8位
char[] stateArray = stateStr.toCharArray();
for(int i=0;i<stateArray.length;i++){
if(stateArray[i]=='1'){
indexs.add(i);
}
}
if (indexs.size()==1 || indexs.size()==8) {
list.add(stateStr);
}else{
list.add(stateStr);
for(int j=0;j<indexs.size();j++){
list.add(returnZeros(indexs.get(j))+"1"+returnZeros(8-indexs.get(j)-1));
for(int k=j+1;k<indexs.size();k++){
list.add(returnZeros(indexs.get(j))+"1"+
returnZeros(indexs.get(k)-indexs.get(j)-1)+"1"+
returnZeros(8-indexs.get(k)-1));
}
}
}
return list;
}[/code]
哦 ,是个10进制与2进制转换问题,这个方法在做权限控制的时候很常见.
你可以参考下:
[url]http://ajax.cnrui.cn/article/52/55/2006/20061116893.shtml[/url]
只要将上面的代码做一点改变就行:
[code="java"] public static void main(String[] args) {
int a = 5;
String s = Integer.toBinaryString(a);
String sql = "select * from t where s="+s;
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(c=='1'){
int t = (int)Math.pow(2, i);
sql += " or s="+Integer.toBinaryString(t)+" ";
}
}
System.out.println(sql);
}[/code]
虽然丑陋,不过你仔细看看就会明白其中的原理.你的规律是将10进制转换成2进制的加减,比如 9 = 2^3 + 2^0 ,原理就是这样.
你在查询的时候,先计算除状态对应的bit(8) 或者整型的状态,到数据库中你可以用like或者完全相等
select state from table where state like '%value%'
或者
select state from table where state = value;
建议在数据库中用整型来表示状态,Null表示无状态,0,1,2,3,4,5分别表示其他状态
前台查询直接传值,不要计算成其他,这样放别得多,也便于理解.不然每次还要去计算一下.
bit的这个用法,感觉很像一个权限控制算法中的做法.用2进制位来表示权限大小.
[quote]如果前台传入一个3就是 00000011,表示把存在后两个状态其一或者全部的都查出来[/quote]
这个的意思是不是要查询出 00000001 00000010 00000011这3种状态?
如果是这样的话,你只需要将10进制转换成2进制,然后一个循环来生成sql条件.
[code="java"]
public static void main(String[] args) {
String sql = "select * from t where ";
int a = 3;
for(int i=1;i<=3;i++){
String t = i==1?"":"or "; //第一个不需要or
sql += t+"s="+Integer.toBinaryString(i)+" "; //十进制转化为2进制字符串
}
System.out.println(sql);
}
[/code]
最后生成的代码如:
[code="java"]select * from t where s=1 or s=10 or s=11 [/code]
因为你说这个字段是integet类型的,所以这样应该可以比较出大小.前面多少个0都不会有影响吧.
如果实在是要长度都一样的话,那你就在Integer.toBinaryString(i)这加个判断,在前面补几个0就行了.