sql关于选择的问题 - 琐碎?

时间:2011-08-05 07:08:01

标签: sql sql-server

似乎微不足道,但无法找到解决方案 -

我需要编写查询,根据属性值获取人员 (例如,让我有attr'1'和'2'和'3'的人)

* 澄清:可以对三个以上的属性值进行查询 - 它将由用户选择 - 从0到n值,但我不期望超过7个值... *

-- tsql script --------------
create table ##temp (person char(1), attr char(1)  );

-- can be 1..n persons and 1..n attributes
insert into ##temp VALUES 
('A','1'),
('A','2'),
('B','1'),
('C','2');

-- sample: get all persons which have attribute 1 AND 2
-- sample: result should be 'A' only

drop table ##temp
-- tsql script -----------------

感谢您的帮助, HH

5 个答案:

答案 0 :(得分:5)

您可以使用带有GROUP BY子句的HAVING COUNT(DISTINCT)

SQL语句

SELECT  person
FROM    ##temp
WHERE   attr IN ('1', '2')
GROUP BY 
        person
HAVING  COUNT(DISTINCT attr) = 2

以下语句将始终优于COUNT(DISTINCT),但如果存在重复项,则会产生不正确的结果。 请注意,优异表现可能无法衡量

SELECT  person
FROM    ##temp
WHERE   attr IN ('1', '2')
GROUP BY 
        person
HAVING  COUNT(*) = 2

答案 1 :(得分:1)

您可以将表格加入到自身:

select t1.person
from ##temp t1
inner join ##temp t2 on t2.person = t1.person and t2.attr = '2'
where t1.attr = '1'

由于这需要为每个添加的属性进行另一次连接,因此它不是很灵活。另一方面,如果你添加distinct,它也会处理重复的属性。

答案 2 :(得分:1)

正常情况下,你有一张桌子,每个人单独列出一个人, 以及带有属性的第二个表

select person from (
  select person, count(person) as cnt from ##temp where attr in (1,2,3) group by person
) where cnt = 3

这应该做的工作

但在您的测试表中只有attr 1和2 ...所以这不会显示任何结果

select person from (
  select person, count(person) as cnt from ##temp where attr in (1,2) group by person
) where cnt = 2

会告诉你A

答案 3 :(得分:0)

如果我理解正确并且您希望这是动态的,那么您必须使用动态sql 来构建查询

SELECT person FROM ###temp WHERE attr = '1' AND attr = '2'

使用您要搜索的数据构建 WHERE 部分。然而,由于它以查询优化的形式带来的限制,这不是一个好主意。因此,更好的方法是将 attrs 作为逗号分隔的字符串并使用split函数将其拆分。然后可以将其结果插入到另一个临时表中,并在主查询中使用,并能够保留查询分析器可以为您完成的大部分优化。

分割功能的一个例子可能是

CREATE FUNCTION dbo.Split(@String varchar(8000), 
                          @Delimiter char(1))       
returns @temptable TABLE (items varchar(8000))       
as       
begin       
    declare @idx int       
    declare @slice varchar(8000)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx)       
        if len(@String) = 0 break       
    end   
return       
end

然后,您可以执行类似

的查询
SELECT person 
FROM ###temp
WHERE attr IN(SELECT CONVERT(int, items) FROM dbo.Split(@attrs, ','))
GROUP BY person 
HAVING ( COUNT(person) = @numattrs )

@numattrs 值应该是您在搜索中使用的属性数。提供给您的程序或使用

之类的东西获取
SELECT COUNT(*) FROM dbo.Split(@attrs, ',')
祝你好运!

答案 4 :(得分:0)

我认为这样做不会有所帮助:

SELECT person FROM ###temp WHERE attr = '1' AND attr = '2' 

没有attr值永远是1和2同时!!

如果你使你的attr字段bigint,并使用二进制值1,2,4,8,16等,那么

select person from table group by person having sum (attr) = 3

会找到人的条目为1,条目为2(完全)。 类似地

having sum(attr) | 11表示它包括1,2和8以及其他人。查找按位函数OR,AND NOT等 注意这受bigint的限制,即你可以有大约63个不同的attr值。