【问题标题】:Query for Min, Max, Avg, and Last Value in TSQL在 SQL 中查询最小值、最大值、平均值和最后一个值
【发布时间】:2018-01-31 14:18:16
【问题描述】:

我正在尝试在单个查询中查找列的最大值、最小值、平均值和最后一个值。 平台:SQL Server 2012

样本表:

SN  Month  Acc  Bal
------------------------
1     7    101   1,000/-
2     7    101   1,500/-
3     7    101   1,700/-
4     8    101   1,200/-
5     8    101   900/-
6     9    101   2,500/-

我写的查询:

select 
    [Month], [Acc],
    min(Bal) as MinBal,
    avg(Bal) as AvgBal,
    max(Bal) as MaxBal
    --, ??? for as LastBal
from 
    MyTable
Group By 
    [Month], [Acc]

使用Last_Value 查询返回所有记录而不是聚合记录

select 
    [Month], [Acc],
    min(Bal) as MinBal,
    avg(Bal) as AvgBal,
    max(Bal) as MaxBal,
    LAST_VALUE(Bal) OVER (partition by [Acc] order by [Month]) as LastBal
from 
    MyTable
Group By 
    [Month], [Acc], Bal

还包括 last_value(bal) 正在生成一个错误,其中 bal 需要按列表分组

选择列表中的“Bal”列无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。

【问题讨论】:

  • LAST_VALUE,也许?
  • 定义你对last的定义。
  • last_value 给了我所有记录,而不是汇总的几条记录
  • 试试LAST_VALUE(Bal) OVER (partition by [Acc], [Month] order by SN)
  • 添加 last_value 要求我按列表添加 bal 列

标签: sql-server database tsql


【解决方案1】:

请试试这个解决方案-

数据生成

CREATE TABLE Alls
(
     SN INT
    ,[Month] INT
    ,Acc INT
    ,Bal INT
)
GO

INSERT INTO Alls VALUES
(1,  7,    101,   1000),
(2,  7,    101,   1500),
(3,  7,    101,   1700),
(4,  8,    101,   1200),
(5,  8,    101,   900),
(6,  9,    101,   2500)
GO

解决方案

SELECT sn,Acc,[Month] ,Bal
, MIN(Bal) OVER(PARTITION BY Acc,[Month]) MinBal
, AVG(Bal*1.) OVER(PARTITION BY Acc,[Month]) AvgBal
, MAX(Bal) OVER(PARTITION BY Acc,[Month]) MaxBal
, FIRST_VALUE(Bal) OVER(PARTITION BY Acc,[Month] ORDER BY SN DESC) lastVal
FROM Alls
ORDER By SN

输出

sn          Acc         Month       Bal         MinBal      AvgBal           MaxBal      lastVal
----------- ----------- ----------- ----------- ----------- ---------------- ----------- -----------
1           101         7           1000        1000        1400.000000      1700        1700
2           101         7           1500        1000        1400.000000      1700        1700
3           101         7           1700        1000        1400.000000      1700        1700
4           101         8           1200        900         1050.000000      1200        900
5           101         8           900         900         1050.000000      1200        900
6           101         9           2500        2500        2500.000000      2500        2500

(6 rows affected)

如果您只需要 acc、month 和其他聚合列,请使用以下 -

解决方案

SELECT Acc,[Month],MAX(MinBal)MinBal,MAX(AvgBal)AvgBal,MAX(MaxBal)MaxBal,MAX(lastVal)lastVal
FROM
(
    SELECT sn,Acc,[Month] ,Bal
    , MIN(Bal) OVER(PARTITION BY Acc,[Month]) MinBal
    , AVG(Bal*1.) OVER(PARTITION BY Acc,[Month]) AvgBal
    , MAX(Bal) OVER(PARTITION BY Acc,[Month]) MaxBal
    , FIRST_VALUE(Bal) OVER(PARTITION BY Acc,[Month] ORDER BY SN DESC) lastVal
    FROM Alls
)u GROUP BY Acc,[Month]

输出

Acc         Month       MinBal      AvgBal           MaxBal      lastVal
----------- ----------- ----------- ---------------- ----------- -----------
101         7           1000        1400.000000      1700        1700
101         8           900         1050.000000      1200        900
101         9           2500        2500.000000      2500        2500

(3 rows affected)

【讨论】:

  • 您的解决方案完美运行...顺便说一句,为什么 avg(Bal*1.) 用于 avg 以及性能问题可能是什么
  • 使 Bal 数字化以防万一我们在 bal 列中有十进制值,否则 avg 将不正确。请看这个例子 - SELECT a, AVG(a*1.) OVER() decimalValuesavg , AVG(a) OVER() normalavgvalues FROM (SELECT 1 a UNION ALL SELECT 2)b
【解决方案2】:
select * 
from 
( SELECT sn, Acc, [Month], Bal
       , MIN(Bal) OVER(PARTITION BY Acc, [Month]) MinBal
       , AVG(Bal) OVER(PARTITION BY Acc, [Month]) AvgBal
       , MAX(Bal) OVER(PARTITION BY Acc, [Month]) MaxBal
       , row_number() OVER(PARTITION BY Acc, [Month] ORDER BY SN DESC) as rn 
) tt
where rn = 1
ORDER By sn

【讨论】:

  • 您的查询看起来不错... (y)
【解决方案3】:

你可以实现如下:

select 
 tt.Month
, tt.Acc
, min(Bal) as MinBal
, avg(Bal) as AvgBal 
, max(Bal) as MaxBal
, latest.balance
FROM #tbl1 as tt 
JOIN (
  SELECT 
  id
  ,month
  ,acc
  ,bal as balance
FROM #tbl1 AS t1
WHERE id = (SELECT MAX(id)
                 FROM #tbl1 AS t2 
                 WHERE t1.month = t2.month 
                   AND t1.acc = t2.acc 
                 GROUP BY month, acc)
) as latest
on tt.month = latest.month 
                   AND tt.acc = latest.acc 
Group By tt.Month, tt.Acc, latest.balance


DROP TABLE #tbl1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-26
    • 1970-01-01
    • 2015-04-12
    • 1970-01-01
    • 2017-03-31
    • 2016-01-05
    • 2016-12-29
    • 1970-01-01
    相关资源
    最近更新 更多