我的问题-应用group by
时,我需要对某列的某些条件进行MAX
,但选择该列(而不是我用来评估max的条件)。需要帮助。
例如,假设我有一个名为RuleUID
的列,其值类似70_rule
,110_rule
,120_rule
等。现在我想做这样的事情。
select firstname, lastname, MAX( CAST(SUBSTRING(RuleUID,1,CHARINDEX('_',RuleUID)-1) AS INT) as **?????**
from employee
group by firstname, lastname
在上面的代码片段中,我需要能够选择对应于MAX
标准的RuleUid(在??????中)。我该怎么办。
您可以使用order by
并以降序获得top 1
。
sql服务器
select firstname
, lastname
, RuleUID
from employee
order by substring(RuleUID,1,charindex('_',RuleUID)-1) desc
mysql
select top 1 firstname
, lastname
, RuleUID
from employee
order by substring(RuleUID,1,charindex('_',RuleUID)-1) desc
limit 1
看来您需要将数字从RuleUID中抽出很多。因此,使一个函数可以重用:
CREATE FUNCTION dbo.getRuleNo(@ruleUID varchar(50))
RETURNS int
AS
BEGIN
RETURN CAST(SUBSTRING(@ruleUID, 1, CHARINDEX('_',@ruleUID) - 1) AS INT)
END;
GO
然后将该函数用于此问题和其他问题:
select firstname,
lastname,
CAST(MAX(dbo.getRuleNo(RuleUID)) AS VARCHAR) + '_rule' as MaxRule
from employee
group by firstname, lastname
select firstname,
lastname,
replace(ltrim(replace(MAX(RIGHT('0000000000' + RuleUID, 10)), '0', ' ')), ' ', '0')
as MaxRule
from employee
group by firstname, lastname
有多种解决方法。一种是将RuleUID
的相同子字符串与MAX
值进行比较:
SELECT firstname, lastname, RuleUID
FROM employee
WHERE CAST(SUBSTRING(RuleUID,1,CHARINDEX('_',RuleUID)-1) AS INT) =
(SELECT MAX(CAST(SUBSTRING(RuleUID,1,CHARINDEX('_',RuleUID)-1) AS INT))
FROM employee)
[另一个是将值的_rule
部分加回MAX
值,然后直接进行比较。这应该更有效,因为您可以在RuleUID
上使用索引:
SELECT firstname, lastname, RuleUID
FROM employee
WHERE RuleUID = (SELECT CONCAT(MAX(CAST(SUBSTRING(RuleUID,1,CHARINDEX('_',RuleUID)-1) AS INT)), '_rule')
FROM employee)
如果您不想使用子查询,则可以将CTE
与ROW_NUMBER()
一起使用:
WITH CTE AS (
SELECT firstname, lastname, RuleUID,
ROW_NUMBER() OVER (ORDER BY CAST(SUBSTRING(RuleUID,1,CHARINDEX('_',RuleUID)-1) AS INT) DESC) AS rn
FROM employee)
SELECT firstname, lastname, RuleUID
FROM CTE
WHERE rn = 1
或RANK()
:
WITH CTE AS (
SELECT firstname, lastname, RuleUID,
ROW_NUMBER() OVER (ORDER BY CAST(SUBSTRING(RuleUID,1,CHARINDEX('_',RuleUID)-1) AS INT) DESC) AS rn
FROM employee)
SELECT firstname, lastname, RuleUID
FROM CTE
WHERE rn = 1
最后,您可以使用简单的TOP
查询:
SELECT TOP 1 firstname
, lastname
, RuleUID
FROM employee
ORDER BY CAST(SUBSTRING(RuleUID,1,CHARINDEX('_',RuleUID)-1) AS INT) DESC
在所有情况下,对于我的演示,输出都是相同的:
firstname lastname RuleUID
someone else 120_rule
首先,我们按LEN(RuleUID)DESC排序。然后通过RuleUID DESC。第一个是您的最高现在您不需要GROUP BY。
;WITH cte AS
(
SELECT LastName, FirstName, RuleUID,
ROW_NUMBER() OVER (PARTITION BY LastName, FirstName
ORDER BY LEN(RuleUID) DESC, RuleUID DESC) AS rn
FROM Employees
)
SELECT *
FROM cte
WHERE rn = 1
ORDER BY LastName, FirstName
这应该为每个名称提供1行以及它们的最大RuleUID。