Pregunta

Tengo la siguiente tabla en MSSQL2005

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

Y ahora quiero agrupar basado en business_key que devuelve la entrada completa con la identificación más alta. Entonces mi resultado esperado es:

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

Apuesto a que hay una manera de lograrlo, simplemente no puedo verlo en este momento.

¿Fue útil?

Solución

Una solución alternativa, que puede brindarle un mejor rendimiento (pruebe en ambos sentidos y verifique los planes de ejecución):

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

Esta consulta asume que el ID es un valor único (al menos para cualquier clave_empresarial) y que está establecido en NOT NULL.

Otros consejos

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

Prueba esto

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

EDITAR: creé la tabla para probar mi código. Lo incluyo a continuación en caso de que alguien más quiera probarlo.

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
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

Esta es una publicación anterior pero era relevante para algo que estaba haciendo actualmente (2013). Si obtiene un conjunto de datos más grande (típico en la mayoría de los DB), el rendimiento de las diversas consultas (mirando los planes de ejecución) dice mucho. Primero creamos una tabla "TALLY" para generar números al azar, luego use una fórmula arbitraria para crear datos para el " 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

A continuación, ejecutamos tres tipos diferentes de consultas para revisar el rendimiento (active "Plan de ejecución real" si está utilizando 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

Limpieza:

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

Encontrará, mirando los planes de ejecución, " Pruebe 1 " tiene el mejor "Costo de consulta" y el tiempo de CPU más bajo pero '' Prueba 3 '' tiene la menor cantidad de lecturas y el tiempo de CPU no es tan malo. Recomendaría usar un método CTE para las lecturas menos

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top