SQL, max (), группировка по - PullRequest
       25

SQL, max (), группировка по

1 голос
/ 30 октября 2019

Мой вопрос - при применении group by мне нужно сделать 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

В приведенном выше фрагменте я должен иметь возможность выбрать RuleUid (в ????? ), который соответствует этому критерию MAX. Как мне поступить об этом.

Ответы [ 5 ]

0 голосов
/ 30 октября 2019

Сначала мы сортируем по 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.

0 голосов
/ 30 октября 2019

Похоже, вам нужно будет много вытащить номер из 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 голосов
/ 30 октября 2019
    select firstname, 
    lastname, 
    replace(ltrim(replace(MAX(RIGHT('0000000000' + RuleUID, 10)), '0', ' ')), ' ', '0')
        as MaxRule
    from employee
    group by firstname, lastname
0 голосов
/ 30 октября 2019

вы можете использовать order by и получить top 1 в порядке убывания.

sql server

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 голосов
/ 30 октября 2019

Есть несколько способов решить эту проблему. Один из них - сравнить одну и ту же подстроку 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

демо на dbfiddle

...