0 0

关于sql中bit位的查询3

postgresql:表中有个状态字段integet类型的,用于表示转换为bit(8)后的0、1状态。
例如1转换成00000001后,最后一位1表示某一个状态,0就表示没有某状态。

这8个状态分别用十进制的0,1,2,4...表示,已经在java中定义成常量了。

前台查询这个表时,传入多个状态,包含其中一个或者多个状态的数据都要查出来。

该怎么传数据、写SQL...

不知道说的清楚不?

如果前台传入一个3就是 00000011,表示把存在后两个状态其一或者全部的都查出来。但在sql里怎么进行判断呢?

后者前台不传入3而是其他结构的特定数据/??  没想到好的办法,

传什么样的数据 ,还有SQL怎么写??? 哪位有经验的给个思路。后者给个sql。

thanks!!!
问题补充:
我也试过这样开些动态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++){  
           }  

肯定是不对的。。。咋办??
问题补充:
谢谢yourgame、playfish的回答。也给我思路。
playfish最后给出的结果还只是一个子集,没有组合结果。
我自己写了个方法,实验下好像没问题,但是还是感觉太麻烦,还是这东西本来就很麻烦?sql几个or下来估计很慢。。。
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;
	}
2009年3月22日 01:35

3个答案 按时间排序 按投票排序

0 0

采纳的答案



哦 ,是个10进制与2进制转换问题,这个方法在做权限控制的时候很常见.

你可以参考下:

http://ajax.cnrui.cn/article/52/55/2006/20061116893.shtml

只要将上面的代码做一点改变就行:


	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);
	}


虽然丑陋,不过你仔细看看就会明白其中的原理.你的规律是将10进制转换成2进制的加减,比如 9 = 2^3 + 2^0 ,原理就是这样.

2009年3月22日 14:51
0 0


bit的这个用法,感觉很像一个权限控制算法中的做法.用2进制位来表示权限大小.

引用
如果前台传入一个3就是 00000011,表示把存在后两个状态其一或者全部的都查出来


这个的意思是不是要查询出 00000001 00000010 00000011这3种状态?

如果是这样的话,你只需要将10进制转换成2进制,然后一个循环来生成sql条件.

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);
	}



最后生成的代码如:

select * from t where s=1 or s=10 or s=11 


因为你说这个字段是integet类型的,所以这样应该可以比较出大小.前面多少个0都不会有影响吧.

如果实在是要长度都一样的话,那你就在Integer.toBinaryString(i)这加个判断,在前面补几个0就行了.

2009年3月22日 09:57
0 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分别表示其他状态
前台查询直接传值,不要计算成其他,这样放别得多,也便于理解.不然每次还要去计算一下.

2009年3月22日 07:50

相关推荐

Global site tag (gtag.js) - Google Analytics