SQL聚合位列到单位结果

时间:2014-03-03 16:10:29

标签: sql sql-server sql-server-2008

我有以下格式的行:

enter image description here

我想要一个SQL查询,它将按EntityId对上述行进行分组,并按以下方式聚合位列:

  • 已提交:如果给定EntityId的任何行为0,则为0,否则为1
  • 已审核:如果给定EntityId的任何行为0,则为0,否则为1
  • 查询:如果给定EntityId 1的任何行,则为1,否则为0

我知道我可以通过将位列转换为int并使用Min / Max来实现这一点,但感觉有点像黑客。我想我的日子很慢,错过了明显的解决方案......

这样做的最佳方式是什么?

我使用的是SQL Server 2008 R2,尽管一般的SQL方法最好。

更新

上述行的所需结果集将为:

enter image description here

5 个答案:

答案 0 :(得分:3)

我认为转换为int可能是最好的,因为没有按位聚合,其他任何东西也都是“hacky”。​​

为了好玩,这应该可以在不投射位字段的情况下工作;

select
  EntityId,
  1 ^ count(distinct nullif(Submitted, 1)),
  1 ^ count(distinct nullif(Reviewed, 1)),
  count(distinct nullif(Query, 0))
from t
group by EntityId

答案 1 :(得分:2)

依赖隐式数据转换:

select entityId
,max(1*submitted)  as submitted
,max(1*reviewed) as reviewed
,max(1*query) as query
from sd_test
group by entityId
order by entityId;

select entityId
,max(sign(submitted))  as submitted
,max(sign(reviewed)) as reviewed
,max(sign(query)) as query
from sd_test
group by entityId
order by entityId

健康警告:

  

SIGN:Arguments

     

numeric_expression是精确数字或表达式   近似数值数据类型类别,位数据类型除外。

它适用于位数据类型。由于位可以是0或1,因此符号将始终返回1或0(但实际上,它可能返回-1,0,1)

select sign(cast(1 as bit)); --returns:1
select sign(cast(0 as bit)); --returns:0

答案 2 :(得分:1)

你想要结果中的位,对吗?

SELECT
    t.EntityId,
    CAST(MIN(CAST(t.Submitted AS INT)) AS BIT) AS Submitted,
    CAST(MIN(CAST(t.Reviewed AS INT)) AS BIT) AS Reviewed,
    CAST(MAX(CAST(t.Query AS INT)) AS BIT) AS Query
FROM YourTable t
GROUP BY t.EntityId

答案 3 :(得分:0)

如果我理解你是对的,你想要这样的东西:

测试数据:

DECLARE @tbl TABLE(EntityId INT,Submitted BIT, Reviewed BIT,Query BIT)
INSERT INTO @tbl VALUES
        (36,1,0,0),
        (52,1,0,0),
        (52,1,1,0),
        (56,1,0,0),
        (56,1,1,0),
        (57,1,0,0),
        (57,1,1,0)

然后是这样的查询:

SELECT
    table1.EntityId,
    MIN(CAST(Submitted AS INT)) AS Submitted,
    MIN(CAST(Reviewed AS INT)) AS Reviewed,
    MAX(CAST(Query AS INT)) AS Query
FROM
    @tbl as table1
GROUP BY
    table1.EntityId 

答案 4 :(得分:0)

为了一点乐趣,我把它扔在了一起。与先前的答案不同,它不使用任何铸造或转换......

DECLARE @tbl table (
   EntityId  int
 , Submitted bit
 , Reviewed  bit
 , Query     bit
);

INSERT INTO @tbl
  VALUES (36, 1, 0, 0)
       , (52, 1, 0, 0)
       , (52, 1, 1, 0)
       , (56, 1, 0, 0)
       , (56, 1, 1, 0)
       , (57, 1, 0, 0)
       , (57, 1, 1, 0)
;

SELECT DISTINCT
       base.EntityId
     , Coalesce(submitted.Submitted, 0) As Submitted
     , Coalesce(reviewed.Reviewed  , 0) As Reviewed
     , Coalesce(query.Query        , 1) As Query
FROM   @tbl As base
 LEFT
  JOIN @tbl As submitted
    ON submitted.EntityId = base.EntityId
   AND submitted.Submitted = 1
 LEFT
  JOIN @tbl As reviewed
    ON reviewed.EntityId = base.EntityId
   AND reviewed.Reviewed = 1
 LEFT
  JOIN @tbl As query
    ON query.EntityId = base.EntityId
   AND query.Query = 0
;

结果:

EntityId    Submitted   Reviewed    Query
----------- ----------- ----------- -----------
36          1           0           0
52          1           1           0
56          1           1           0
57          1           1           0