SQL,max(),分组依据

问题描述 投票:1回答:4

我的问题-应用group by时,我需要对某列的某些条件进行MAX,但选择该列(而不是我用来评估max的条件)。需要帮助。

例如,假设我有一个名为RuleUID的列,其值类似70_rule110_rule120_rule等。现在我想做这样的事情。

select firstname, lastname, MAX( CAST(SUBSTRING(RuleUID,1,CHARINDEX('_',RuleUID)-1) AS INT) as **?????**
from employee
group by firstname, lastname

在上面的代码片段中,我需要能够选择对应于MAX标准的RuleUid(在??????中)。我该怎么办。

sql group-by max
4个回答
0
投票

您可以使用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

0
投票

看来您需要将数字从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

0
投票
    select firstname, 
    lastname, 
    replace(ltrim(replace(MAX(RIGHT('0000000000' + RuleUID, 10)), '0', ' ')), ' ', '0')
        as MaxRule
    from employee
    group by firstname, lastname

0
投票

有多种解决方法。一种是将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)

如果您不想使用子查询,则可以将CTEROW_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

Demo on dbfiddle


0
投票

首先,我们按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。

© www.soinside.com 2019 - 2024. All rights reserved.