根据同一列上的不同条件进行聚合

时间:2018-04-04 15:16:45

标签: sql sql-server tsql

我有一个像@tbl一样的表,我需要写一个查询,好像有3个以上的记录可用 对于特定的cid,特定cid的avg(特定cid的val)应该针对每个id显示,如果小于 3个记录可用于特定的cid然后avg(所有记录的val可用)。

请建议。

declare @tbl table(id int, cid int, val float )

insert into @tbl 
values(1,100,20),(2,100,30),(3,100,25),(4,100,31),(5,100,50),
(6,200,30),(7,200,30),(8,300,90)

3 个答案:

答案 0 :(得分:2)

您的描述不明确,但我相信您需要加窗功能:

WITH cte AS (
  SELECT *, COUNT(*) OVER(PARTITION BY cid) AS cnt
  FROM @tbl
)
SELECT id, (SELECT AVG(val) FROM cte) AS Av
FROM cte
WHERE cnt <=3
UNION ALL
SELECT id, AVG(val) OVER(PARTITION BY cid) AS Av
FROM cte
WHERE cnt > 3
ORDER BY id;

<强> DBFiddle Demo

修改

SELECT id,
    CASE WHEN COUNT(*) OVER(PARTITION BY cid) <= 3 THEN AVG(val) OVER() 
         ELSE AVG(val) OVER(PARTITION BY cid)
    END
FROM @tbl
ORDER BY id;

<强> DBFiddle Demo2

答案 1 :(得分:0)

您可以尝试以下操作。首先计算每个Cid的平均值,具体取决于它的出现次数,然后将每个Id加入;WITH CidAverages AS ( SELECT T.cid, Average = CASE WHEN COUNT(1) >= 3 THEN AVG(T.val) ELSE (SELECT AVG(Val) FROM @tbl) END FROM @tbl AS T GROUP BY T.cid ) SELECT T.*, C.Average FROM @tbl AS T INNER JOIN CidAverages AS C ON T.cid = C.cid 以显示所有表格。

textContent

答案 2 :(得分:0)

鉴于评论中的澄清,我认为这是意图

declare @tbl table(id int, cid int, val float )

insert into @tbl 
values(1,100,20),(2,100,30),(3,100,25),(4,100,31),(5,100,50),
(6,200,30),(7,200,30),(8,300,90);
select distinct
    cid
    , case
    when count(*) over (partition by cid) > 3 then avg(val) over (partition by cid)
    else avg (val) over (partition by 1)
    end as avg
from @tbl;

http://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=fdf4c4457220ec64132de7452a034976

cid avg
100 31.2 
200 38.25 
300 38.25

像这样的查询有很多方面,虽然在规模上运行虽然在查询计划上会非常糟糕,但我想在更大的范围内进行测试并在使用前进行调整。

描述不清楚发生了什么,如果它正好是3,它提到“超过3”和“少于3” - 在这段代码中,“超过”用于确定它所属的类别,以及小于被解释为'小于或等于3'