位列中的按位比较

时间:2018-03-09 13:13:29

标签: sql sql-server

我有一个数据库表,其列的形状如下:

| ID | name | A | B | C | D |
|  1 |  foo | 1 | 0 | 0 | 1 |
|  2 |  bar | 0 | 0 | 1 | 1 |
|  3 |  foo | 1 | 1 | 0 | 0 |
|  4 |  bar | 1 | 1 | 0 | 0 |

A,B,C和D是位列。

我需要获取至少有两行的名称值,并且至少有一个相同的位列设置为true。我希望得到的结果集如下:

| name | 
|  foo | 

我可以做以下事情:

SELECT l.name
FROM dummy l
INNER JOIN dummy r ON l.name = r.name
WHERE (l.A = 1 AND r.A = 1) 
OR (l.B = 1 AND r.B = 1) 
OR (l.C = 1 AND r.C = 1)
OR (l.D = 1 AND r.D = 1)
GROUP BY l.name
HAVING COUNT(*) > 1

但由于桌子庞大,这很快就会变得难以理解。我想知道是否有一个按位解决方案来解决这个问题

4 个答案:

答案 0 :(得分:2)

我怀疑你的数据模型是错误的。感觉AD代表相同的“类型”事物,因此数据应该使用单个列表示包含数据值AD和(如果需要)一个用于存储1或0的列,每个AD值具有单独的。 (但是,当然,我们可以使用行的存在来表示1而没有行来表示0)。

我们可以使用UNPIVOT为数据创建“更好”的结构,然后查询变得琐碎

declare @t table (ID int not null, name char(3) not null, A bit not null, B bit not null,
                                                          C bit not null, D bit not null)
insert into @t(ID,name,A,B,C,D) values
(1,'foo',1,0,0,1),
(2,'bar',0,0,1,1),
(3,'foo',1,1,0,0),
(4,'bar',1,1,0,0)

;With ProperLayout as (
    select ID,Name,Property,Value
    from @t t
        unpivot (Value for Property in (A,B,C,D)) u
    where Value = 1
)
select name,Property
from ProperLayout
group by name,Property
having COUNT(*) > 1

结果:

name Property
---- ---------
foo  A

(另请注意,我的脚本顶部与您问题中的示例数据的大小差别不大,但它具有 runnable 的巨大好处)

答案 1 :(得分:2)

以类似的方式,你也可以使用 Apply opertaor

private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    MessageBox.Show("Done...");
    label1.Visible = false;
    progressBar1.Visible = false;
}

答案 2 :(得分:0)

根据您的描述,您似乎想要:

SELECT l.name
FROM dummy l
GROUP BY l.name
HAVING SUM( CAST(A as int) ) >= 2 OR
       SUM( CAST(B as int) ) >= 2 OR
       SUM( CAST(C as int) ) >= 2 OR
       SUM( CAST(D as int) ) >= 2 ;

这是基于描述。我不知道相同的结果行与问题有什么关系。

答案 3 :(得分:0)

不难阅读。这很长。
这会更有效:

SELECT distinct l.name
FROM       dummy l
INNER JOIN dummy r 
   ON l.name = r.name
  and l.id < r.id 
  and (    (l.A = 1 AND r.A = 1) 
        OR (l.B = 1 AND r.B = 1) 
        OR (l.C = 1 AND r.C = 1)
        OR (l.D = 1 AND r.D = 1) 
      )
order by l.name

您可以在阅读sys.columns

的基础上构建它

我不认为TSQL有任何按位运算符。