SQL Server: только последняя запись в GROUP BY

У меня есть следующая таблица в MSSQL2005

id | business_key | result
1 | 1 | 0
2 | 1 | 1
3 | 2 | 1
4 | 3 | 1
5 | 4 | 1
6 | 4 | 0

И теперь я хочу сгруппировать на основе business_key, возвращающего полную запись с наивысшим идентификатором. Итак, мой ожидаемый результат:

business_key | result
1 | 1
2 | 1
3 | 1
4 | 0

Могу поспорить, что есть способ добиться этого, я просто не вижу этого в данный момент.

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
7
0
15 834
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

select
  drv.business_key,
  mytable.result
from mytable
  inner join
  (
    select 
      business_key, 
      max(id) as max_id
    from mytable
    group by
      business_key
  ) as drv on
    mytable.id = drv.max_id

Попробуй это

select  business_key, 
        result
from    myTable
where   id in 
        (select max(id)
        from    myTable
        group by business_key)

Обновлено: я создал таблицу для проверки своего кода. Я включаю его ниже на случай, если кто-то еще захочет его протестировать.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[myTable](
    [id] [int] NOT NULL,
    [business_key] [int] NOT NULL,
    [result] [int] NOT NULL
) ON [PRIMARY]
go

insert into myTable values(1,1,0);
insert into myTable values(2,1,1);
insert into myTable values(3,2,1);
insert into myTable values(4,3,1);
insert into myTable values(5,4,1);
insert into myTable values(6,4,0);

select  * from mytable

Этот запрос покажет только одну строку данных, а не четыре. Вам нужно сделать коррелированный подзапрос - и вам нужны псевдонимы для двух экземпляров MyTable (назовите их «первым» и «вторым»); добавить ГДЕ first.id = second.id

Jonathan Leffler 13.01.2009 17:17

Джонатан: Вы правы, в предложении where допущена опечатка. Это должно быть 'in', а не '='. Но псевдоним не нужен. Спасибо за указание на мою ошибку.

John MacIntyre 13.01.2009 17:32
Ответ принят как подходящий

Альтернативное решение, которое может дать вам лучшую производительность (протестируйте оба способа и проверьте планы выполнения):

SELECT
     T1.id,
     T1.business_key,
     T1.result
FROM
     dbo.My_Table T1
LEFT OUTER JOIN dbo.My_Table T2 ON
     T2.business_key = T1.business_key AND
     T2.id > T1.id
WHERE
     T2.id IS NULL

В этом запросе предполагается, что идентификатор является уникальным значением (по крайней мере, для любого заданного business_key) и установлен в NOT NULL.

вау, ты прав. Запрос стоит 44% вместо 56%. Большое спасибо!

computhomas 13.01.2009 17:08

Вот что я здесь искал: stackoverflow.com/questions/20934092/…

Hitesh Gawhade 06.01.2014 08:41
select business_key, 
       result
    from 
    (select id, 
        business_key, 
        result, 
        max(id) over (partition by business_key) as max_id
    from mytable) x
where id = max_id

Это должен быть принятый ответ, потому что этот запрос НАМНОГО эффективнее принятого.

Łukasz Wiatrak 17.01.2013 15:47

Вряд ли это так. Я выполнил оба запроса через MSSQL 2012 R2 за один раз, и из полученного плана выполнения я обнаружил, что часть подзапроса использовала 68% затраченного времени. Сама секция использовала 77% всего второго запроса.

Eric Wu 06.03.2016 22:00

Это более старый пост, но он имел отношение к тому, что я делал в настоящее время (2013 г.). Если вы получаете больший набор данных (типичный для большинства БД), производительность различных запросов (с учетом планов выполнения) говорит о многом. Сначала мы создаем «ТАЛИТИЧЕСКУЮ таблицу» для случайного генерирования чисел, а затем используем произвольную формулу для создания данных для «MyTable»:

CREATE TABLE #myTable(
    [id] [int] NOT NULL,
    [business_key] [int] NOT NULL,
    [result] [int] NOT NULL,
    PRIMARY KEY (Id)
) ON [PRIMARY];

; WITH
    -- Tally table Gen            Tally Rows:     X2                X3
t1 AS (SELECT 1 N UNION ALL SELECT 1 N),    -- 4            ,    8
t2 AS (SELECT 1 N FROM t1 x, t1 y),            -- 16            ,    64
t3 AS (SELECT 1 N FROM t2 x, t2 y),            -- 256            ,    4096
t4 AS (SELECT 1 N FROM t3 x, t3 y),            -- 65536        ,    16,777,216
t5 AS (SELECT 1 N FROM t4 x, t4 y),            -- 4,294,967,296,    A lot
Tally AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) N
          FROM t5 x, t5 y)

INSERT INTO #MyTable 
SELECT N, CAST(N/RAND(N/8) AS bigINT)/5 , N%2
FROM Tally
WHERE N < 500000

Затем мы запускаем три разных типа запросов для проверки производительности (включите «Фактический план выполнения», если вы используете SQL Server Management Studio):

SET STATISTICS IO ON
SET STATISTICS TIME ON
----- Try #1 
select  'T1' AS Qry, id, business_key, 
        result
from    #myTable
where   id in 
        (select max(id)
        from    #myTable
        group by business_key)

---- Try #2 
select 'T2' AS Qry, id, business_key, 
       result
    from 
    (select id, 
        business_key, 
        result, 
        max(id) over (partition by business_key) as max_id
    from #mytable) x
where id = max_id

---- Try #3 
;with cteRowNumber as (
    select id, 
        business_key, 
        result,
           row_number() over(partition by business_key order by id desc) as RowNum
        from #mytable
)

SELECT 'T3' AS Qry, id, business_key, 
       result
FROM cteRowNumber
WHERE RowNum = 1

Очистка:

IF OBJECT_ID(N'TempDB..#myTable',N'U') IS NOT NULL 
    DROP TABLE #myTable;
    SET STATISTICS IO OFF
SET STATISTICS TIME OFF

Глядя на планы выполнения, вы обнаружите, что «Попытка 1» имеет лучшую «Стоимость запроса» и самое низкое время ЦП, но «Попытка 3» имеет наименьшее количество чтений, а время ЦП не так уж и плохо. Я бы рекомендовал использовать метод CTE для наименее читаемых

Другие вопросы по теме