我需要获取最大值和最小值,但也需要在同一行获取这些最大值或最小值的行ID。SQL查询最小最大值
SELECT MIN([Value]), MAX([Value]), id
FROM [AnalystEstimates].[dbo].[AnalystEstimateValues]
GROUP BY indicatorid
我需要获取最大值和最小值,但也需要在同一行获取这些最大值或最小值的行ID。SQL查询最小最大值
SELECT MIN([Value]), MAX([Value]), id
FROM [AnalystEstimates].[dbo].[AnalystEstimateValues]
GROUP BY indicatorid
这是很不清楚你想从你的问题。你真的想要GROUP BY indicatorid吗?如果不是那么这很简单,你已经有很多答案。但是,如果你确实想要GROUP BY,那就更困难了,没有人知道它是否正确。我还假设你只需要每个indicatorid一行,并且如果有重复的行具有相同的最大/最小值,那么最好是任意选择其中一个,而不是返回两个行。
这里是我的尝试,使用CTE(需要SQL Server 2005或更新版本):
WITH
RowNumbers AS (
SELECT ROW_NUMBER() OVER (ORDER BY indicatorid, value) AS RowNumber, *
FROM [AnalystEstimates].[dbo].[AnalystEstimateValues]),
MinRowNumbers AS (
SELECT indicatorid, MIN(RowNumber) AS RowNumber FROM RowNumbers GROUP BY indicatorid),
MaxRowNumbers AS (
SELECT indicatorid, MAX(RowNumber) AS RowNumber FROM RowNumbers GROUP BY indicatorid)
SELECT
MinRowNumbers.indicatorid,
RN1.Value AS MinValue,
RN1.ID AS MinValueId,
RN2.Value AS MaxValue,
RN2.ID AS MaxValueId
FROM MinRowNumbers
JOIN MaxRowNumbers ON MinRowNumbers.indicatorid = MaxRowNumbers.indicatorid
JOIN RowNumbers RN1 ON MinRowNumbers.RowNumber = RN1.RowNumber
JOIN RowNumbers RN2 ON MaxRowNumbers.RowNumber = RN2.RowNumber
这里是我用来测试它的一些数据:
CREATE TABLE AnalystEstimateValues (ID int, indicatorid int, Value int);
INSERT INTO AnalystEstimateValues (ID, indicatorid , Value) VALUES
(1, 1, 4),
(2, 1, 4),
(3, 2, 6),
(4, 1, 2),
(5, 2, 2),
(6, 2, 5),
(7, 3, 0);
而这里的输出我得到:
indicatorid MinValue MinValueId MaxValue MaxValueId
1 2 4 4 2
2 2 5 6 3
3 0 7 0 7
如果这不是你想要的,你可以请尝试改善你的问题,告诉我们你想做什么?
更新:这是基于克雷格年轻的答案的替代解决方案,但使用联接,而不是子查询:
WITH
UniqueIds AS (
SELECT IndicatorId, Value, MIN(id) AS Id
FROM AnalystEstimateValues
GROUP BY IndicatorId, Value)
SELECT
lims.IndicatorId,
MinValue,
T1.Id AS MinValueId,
MaxValue,
T2.Id AS MaxValueId
FROM (
SELECT
IndicatorId,
MIN(Value) as MinValue,
MAX(Value) as MaxValue
FROM AnalystEstimateValues
GROUP BY IndicatorId) lims
JOIN UniqueIds T1 ON lims.IndicatorId = T1.IndicatorId AND lims.MinValue = T1.Value
JOIN UniqueIds T2 ON lims.IndicatorId = T2.IndicatorId AND lims.MaxValue = T2.Value
这是更清洁,也可能快于我的第一个版本,虽然我没有运行性能测试来验证这一点。
谢谢 那就是它 – Woland 2009-12-30 09:30:05
好吧,我很幸运。 :)我想下次你应该花更多时间在你的问题上,以便反应更符合你的想法。事实上,我认为这不是解决这个问题的最好方法 - 它可能太慢了。我看到你已经接受了它,但是我希望你已经证实,在你这样做之前,它对于你的数据来说足够快。如果稍后有人能够以更好的方式解决这个问题,那么他们可以看到你想要的东西,那么你应该接受他们的答案而不是这个答案。 – 2009-12-30 09:34:21
我不熟悉你使用的语法;我必须阅读它。作为性能说明,您有2个GROUP BY子查询 - 一个用于MIN,另一个用于MAX。您应该能够将这些结合到一个子查询中并获得显着的性能改进。 – 2009-12-31 08:29:36
当您按照ID进行分组时,您的查询会返回每个ID的最大/最小值。尝试这样的事情
SELECT tblFoo.ID, tblFoo.Value
FROM tblFoo
WHERE (((tblFoo.Value)=(SELECT MAX([tblFoo]![Value]) FROM tblFoo)))
OR (((tblFoo.Value)=(SELECT MIN([tblFoo]![Value]) FROM tblFoo)));
您也失去了分组结构。 – 2009-12-30 08:35:06
SELECT TOP 1
ID,
'min' as type,
value
FROM
AnalystEstimateValues
WHERE
value = (select min(value) from AnalystEstimateValues)
UNION
SELECT TOP 1
ID,
'max' as type,
value
FROM
AnalystEstimateValues
WHERE
value = (select max(value) from AnalystEstimateValues)
您也失去了分组结构。 – 2009-12-30 08:36:10
当Min = Max中,你会一开始同样的ID(也有可能被捆绑最小值和最大值)
如果不是,有/有ID(S )每最小值/最大值。
基本上,您可以有2行或4列。
SELECT
Mn.ID, foo.MinVal,
Mx.ID, foo.MaxVal
FROM
(
SELECT
MIN([Value]) AS MinVal,
MAX([Value]) AS MaxVal,
indicatorid
FROM
[AnalystEstimates].[dbo].[AnalystEstimateValues]
GROUP BY
indicatorid
) foo
JOIN
[AnalystEstimates].[dbo].[AnalystEstimateValues] Mn ON
foo.MinVal = Mn.[Value] AND foo.indicatorid = Mn.indicatorid
JOIN
[AnalystEstimates].[dbo].[AnalystEstimateValues] Mx ON
foo.MaxVal = Mx.[Value] AND foo.indicatorid = Mx.indicatorid
编辑:
的最佳方案不会给你,你已经绑MIN行/ MAX值,除非有了这个可以做它关系
ON foo.MinVal = Mn。[Value] and ON foo.MaxVal = Mx [Value] 是不可能的,因为可能有重复的值 – Woland 2009-12-30 09:24:16
所以:如果有重复项,你想要哪个ID?你会如何决定一个ID比另一个ID? – gbn 2009-12-30 09:26:39
如果您希望允许像这样返回多个结果,则应该在联接中包含indicatorid,否则您可以从错误的组中获取行。即你需要这个:'ON foo.MinVal = Mn。[Value] AND foo.indicatorid = Mn.indicatorid'。 – 2009-12-30 09:49:14
定义,虽然我没有MSSQL所以我无法测试它。特别是方括号可能需要调整。除此之外,它应该是相当标准的SQL,并做你想要的。
它获取由indicatorid分组的所有min(id/value)和max(id/value)。 在同一行。
SELECT mint.indicatorid, mint.min_id, mint.min_value, maxt.max_id, maxt.max_value
FROM (
SELECT indicatorid, id as min_id, MIN([Value]) AS min_value
FROM [AnalystEstimates].[dbo].[AnalystEstimateValues]
HAVING [Value] = min_value
GROUP BY indicatorid
) mint JOIN (
SELECT indicatorid, id as max_id, MAX([Value]) AS max_value
FROM [AnalystEstimates].[dbo].[AnalystEstimateValues]
HAVING [Value] = max_value
GROUP BY indicatorid
) maxt ON mint.indicatorid = maxt.indicatorid
我收到此错误“ID”在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。“ – Woland 2009-12-30 09:13:40
重要的问题
马克·拜尔斯样本数据表明,你需要考虑一个场景:
那么应该显示两个id中的哪一个?
我假定它足以显示最低的ID。以下查询应该是最有效的,并且可以从(indicatorid,Value)上的索引中受益。
SELECT lims.*,
(
SELECT MIN(id)
FROM AnalystEstimateValues m
WHERE m.IndicatorId = lims.IndicatorId
AND m.Value = lims.MinValue
) AS MinId,
(
SELECT MIN(id)
FROM AnalystEstimateValues m
WHERE m.IndicatorId = lims.IndicatorId
AND m.Value = lims.MaxValue
) AS MaxId
FROM (
SELECT IndicatorId,
MIN(Value) as MinValue,
MAX(Value) as MaxValue
FROM AnalystEstimateValues
GROUP BY IndicatorId
) lims
根据我的示例测试数据生成正确的结果。它使用相关子查询,所以我不确定它会一直很快 - 如果有非常多的非常小的指示符组,我怀疑它会变慢。但是,如果不尝试使用更真实的数据,就很难猜测这些东西。我仍然觉得必须有更好的方式来做到这一点,但无论如何+1。 – 2009-12-31 13:47:16
我已经对您的解决方案进行了修改,并将其附加到我的第一个答案的末尾。我基本上做同样的事情,但使用联接而不是相关子选择。我*猜测*这会更快,但需要进行适当的测试才能确定。我不打算这么做 - 创建逼真的测试数据太费力了 - 但如果其他人这样做(Woland?),我会非常有兴趣知道结果。 – 2009-12-31 14:06:14
PS:我猜你的解决方案很好,因为可能并不是那么多的指标。 – 2009-12-31 15:32:08
是否需要ID和MIN,然后是ID和Max。在2行?彼此相邻? – 2009-12-30 08:16:57
是的,它会很酷,如果ID和MIN,然后ID和Max ar彼此相邻 – Woland 2009-12-30 08:20:36
@Woland:您是否介意编辑您的问题以反映更改的要求? – 2009-12-30 08:23:08