如何在 SQL Server 2012 的列中查找最大值
How to find Max value in a column in SQL Server 2012
我想在一列中找到最大值
ID CName Tot_Val PName
--------------------------------
1 1 100 P1
2 1 10 P2
3 2 50 P2
4 2 80 P1
以上是我的table结构。我只想从 table 中找到最大总值。这四行 ID 1 和 2 在 CName
中具有相同的值,但 total val 和 PName
具有不同的值。我期望的是必须在 ID 1 和 2
中找到最大值
预期结果:
ID CName Tot_Val PName
--------------------------------
1 1 100 P1
4 2 80 P1
我需要与上述相同的结果
select Max(Tot_Val), CName
from table1
where PName in ('P1', 'P2')
group by CName
这是我试过的查询,但我的问题是我无法在此 table 中引入 PName。如果我在 select 列表中添加 PName 意味着它将显示加倍的行,例如结果是 100 行,但是当我在 selected 列表中添加 PName 并按列表分组时,它显示 600 行。就是这个问题。
谁能帮我解决这个问题。
一个可能的选择是使用子查询。在按 Tot_Val
排序的每个 CName
组中为每一行指定一个数字。然后select行号等于1的行。
select x.*
from ( select mt.ID,
mt.CName,
mt.Tot_Val,
mt.PName,
row_number() over(partition by mt.CName order by mt.Tot_Val desc) as No
from MyTable mt ) x
where x.No = 1;
另一种方法是使用通用 table 表达式 (CTE) 而不是子查询来隔离第一个结果集。
with x as
(
select mt.ID,
mt.CName,
mt.Tot_Val,
mt.PName,
row_number() over(partition by mt.CName order by mt.Tot_Val desc) as No
from MyTable mt
)
select x.*
from x
where x.No = 1;
在 this fiddle 中查看两种解决方案的实际应用。
您可以在 top-n-per-group 中搜索此类查询。
有两种常用的方法。最有效的方法取决于您的索引和数据分布,以及您是否已经有另一个 table 和所有 CName
值的列表。
- 使用
ROW_NUMBER
WITH
CTE
AS
(
SELECT
ID, CName, Tot_Val, PName,
ROW_NUMBER() OVER (PARTITION BY CName ORDER BY Tot_Val DESC) AS rn
FROM table1
)
SELECT
ID, CName, Tot_Val, PName
FROM CTE
WHERE rn=1
;
- 使用
CROSS APPLY
WITH
CTE
AS
(
SELECT CName
FROM table1
GROUP BY CName
)
SELECT
A.ID
,A.CName
,A.Tot_Val
,A.PName
FROM
CTE
CROSS APPLY
(
SELECT TOP(1)
table1.ID
,table1.CName
,table1.Tot_Val
,table1.PName
FROM table1
WHERE
table1.CName = CTE.CName
ORDER BY
table1.Tot_Val DESC
) AS A
;
查看关于 dba.se Retrieving n rows per group 的非常详细的答案
,或此处 获取每组的前 1 行
.
CROSS APPLY
可能与相关子查询一样快,但这通常具有非常好的性能(并且优于 ROW_NUMBER()
:
select t.*
from t
where t.tot_val = (select max(t2.tot_val)
from t t2
where t2.cname = t.cname
);
注意:性能取决于 (cname, tot_val)
上的索引。
我想在一列中找到最大值
ID CName Tot_Val PName
--------------------------------
1 1 100 P1
2 1 10 P2
3 2 50 P2
4 2 80 P1
以上是我的table结构。我只想从 table 中找到最大总值。这四行 ID 1 和 2 在 CName
中具有相同的值,但 total val 和 PName
具有不同的值。我期望的是必须在 ID 1 和 2
预期结果:
ID CName Tot_Val PName
--------------------------------
1 1 100 P1
4 2 80 P1
我需要与上述相同的结果
select Max(Tot_Val), CName
from table1
where PName in ('P1', 'P2')
group by CName
这是我试过的查询,但我的问题是我无法在此 table 中引入 PName。如果我在 select 列表中添加 PName 意味着它将显示加倍的行,例如结果是 100 行,但是当我在 selected 列表中添加 PName 并按列表分组时,它显示 600 行。就是这个问题。
谁能帮我解决这个问题。
一个可能的选择是使用子查询。在按 Tot_Val
排序的每个 CName
组中为每一行指定一个数字。然后select行号等于1的行。
select x.*
from ( select mt.ID,
mt.CName,
mt.Tot_Val,
mt.PName,
row_number() over(partition by mt.CName order by mt.Tot_Val desc) as No
from MyTable mt ) x
where x.No = 1;
另一种方法是使用通用 table 表达式 (CTE) 而不是子查询来隔离第一个结果集。
with x as
(
select mt.ID,
mt.CName,
mt.Tot_Val,
mt.PName,
row_number() over(partition by mt.CName order by mt.Tot_Val desc) as No
from MyTable mt
)
select x.*
from x
where x.No = 1;
在 this fiddle 中查看两种解决方案的实际应用。
您可以在 top-n-per-group 中搜索此类查询。
有两种常用的方法。最有效的方法取决于您的索引和数据分布,以及您是否已经有另一个 table 和所有 CName
值的列表。
- 使用
ROW_NUMBER
WITH
CTE
AS
(
SELECT
ID, CName, Tot_Val, PName,
ROW_NUMBER() OVER (PARTITION BY CName ORDER BY Tot_Val DESC) AS rn
FROM table1
)
SELECT
ID, CName, Tot_Val, PName
FROM CTE
WHERE rn=1
;
- 使用
CROSS APPLY
WITH
CTE
AS
(
SELECT CName
FROM table1
GROUP BY CName
)
SELECT
A.ID
,A.CName
,A.Tot_Val
,A.PName
FROM
CTE
CROSS APPLY
(
SELECT TOP(1)
table1.ID
,table1.CName
,table1.Tot_Val
,table1.PName
FROM table1
WHERE
table1.CName = CTE.CName
ORDER BY
table1.Tot_Val DESC
) AS A
;
查看关于 dba.se Retrieving n rows per group 的非常详细的答案 ,或此处 获取每组的前 1 行 .
CROSS APPLY
可能与相关子查询一样快,但这通常具有非常好的性能(并且优于 ROW_NUMBER()
:
select t.*
from t
where t.tot_val = (select max(t2.tot_val)
from t t2
where t2.cname = t.cname
);
注意:性能取决于 (cname, tot_val)
上的索引。