我有一个数据库表,其列的形状如下:
| 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
但由于桌子庞大,这很快就会变得难以理解。我想知道是否有一个按位解决方案来解决这个问题
答案 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有任何按位运算符。