Pregunta

OK tengo una tabla como esta:

ID     Signal    Station    OwnerID
111     -120      Home       1
111     -130      Car        1
111     -135      Work       2
222     -98       Home       2
222     -95       Work       1
222     -103      Work       2

Todo esto es por el mismo día.Solo necesito que la consulta devuelva la señal máxima para cada ID:

ID    Signal    Station    OwnerID
111   -120      Home        1
222   -95       Work        1

Intenté usar MAX() y la agregación se estropea porque Station y OwnerID son diferentes para cada registro.¿Necesito unirme?

¿Fue útil?

Solución

Algo como esto? Unirse a su mesa con sí mismo, y excluir a las filas de los que se encontró una señal de alto.

select cur.id, cur.signal, cur.station, cur.ownerid
from yourtable cur
where not exists (
    select * 
    from yourtable high 
    where high.id = cur.id 
    and high.signal > cur.signal
)

Esta sería una lista de una fila para cada señal más alta, lo que podría haber múltiples filas por ID.

Otros consejos

Usted está haciendo un máximo funcionamiento del grupo sabia / mínimo. Esta es una trampa común:. Se siente como algo que debería ser fácil de hacer, pero en SQL que no es aggravatingly

Hay una serie de enfoques (tanto estándar ANSI y específica del proveedor) a este problema, la mayoría de los cuales son sub-óptimos en muchas situaciones. Algunos le dan varias filas cuando más de una fila comparte el mismo valor máximo / mínimo; otros no. Algunos trabajan bien en tablas con un pequeño número de grupos; otros son más eficiente para un mayor número de grupos con filas más pequeñas por grupo.

He aquí una discusión de algunos de los más comunes (MySQL-polarización negativa de aplicación general). Personalmente, si sabemos que no hay múltiples máximos (o no se preocupan por conseguir ellos) A menudo me inclino por el método nula de izquierda autocombinación, que voy a publicar ya que nadie más ha aún:

SELECT reading.ID, reading.Signal, reading.Station, reading.OwnerID
FROM readings AS reading
LEFT JOIN readings AS highersignal
    ON highersignal.ID=reading.ID AND highersignal.Signal>reading.Signal
WHERE highersignal.ID IS NULL;

En el clásico de SQL-92 (no usar las operaciones OLAP utilizados por Quassnoi), entonces usted puede utilizar:

SELECT g.ID, g.MaxSignal, t.Station, t.OwnerID
  FROM (SELECT id, MAX(Signal) AS MaxSignal
          FROM t
          GROUP BY id) AS g
       JOIN t ON g.id = t.id AND g.MaxSignal = t.Signal;

(sintaxis sin control;. Asume su mesa es 't')

El sub-consulta en la cláusula FROM identifica el valor máximo de la señal para cada ID; la unión combina que con la correspondiente fila de datos de la tabla principal.

Nota:. Si hay varias entradas para un ID específico que todos tienen la misma intensidad de señal y que la fuerza es el MAX (), por lo que recibirá varias filas de salida para ese ID


Probado contra IBM Informix Dynamic Server 11.50.FC3 que se ejecutan en Solaris 10:

+ CREATE TEMP TABLE signal_info
(
    id      INTEGER NOT NULL,
    signal  INTEGER NOT NULL,
    station CHAR(5) NOT NULL,
    ownerid INTEGER NOT NULL
);
+ INSERT INTO signal_info VALUES(111, -120, 'Home', 1);
+ INSERT INTO signal_info VALUES(111, -130, 'Car' , 1);
+ INSERT INTO signal_info VALUES(111, -135, 'Work', 2);
+ INSERT INTO signal_info VALUES(222, -98 , 'Home', 2);
+ INSERT INTO signal_info VALUES(222, -95 , 'Work', 1);
+ INSERT INTO signal_info VALUES(222, -103, 'Work', 2);
+ SELECT g.ID, g.MaxSignal, t.Station, t.OwnerID
  FROM (SELECT id, MAX(Signal) AS MaxSignal
            FROM signal_info
            GROUP BY id) AS g
      JOIN signal_info AS t  ON g.id = t.id AND g.MaxSignal = t.Signal;

111     -120    Home    1
222     -95     Work    1

puse el nombre de la tabla Signal_Info para esta prueba - pero parece que para producir la respuesta correcta. Esto sólo muestra que hay al menos un DBMS que soporta la notación. Sin embargo, estoy un poco sorprendido de que MS SQL Server no hace -? Qué versión está usando


Nunca deja de sorprenderme la frecuencia con preguntas SQL se sometió sin nombres de tabla.


with tab(id, sig, sta, oid) as
(
select 111 as id, -120 as signal, 'Home' as station, 1 as ownerId union all
select 111, -130, 'Car',  1 union all
select 111, -135, 'Work', 2 union all
select 222, -98, 'Home',  2 union all
select 222, -95, 'Work',  1 union all
select 222, -103, 'Work', 2
) ,
tabG(id, maxS) as
(
   select id, max(sig) as sig from tab group by id
)
select g.*, p.* from tabG g
cross apply ( select  top(1) * from tab t where t.id=g.id order by t.sig desc ) p

WITH q AS
         (
         SELECT  c.*, ROW_NUMBER() OVER (PARTITION BY id ORDER BY signal DESC) rn
         FROM    mytable
         )
SELECT   *
FROM     q
WHERE    rn = 1

Esto le devolverá una fila, incluso si no son duplicados de MAX(signal) para un ID dado.

Tener un índice en (id, signal) mejorará en gran medida esta consulta.

Podemos hacerlo usando la autounión.

SELECT  T1.ID,T1.Signal,T2.Station,T2.OwnerID
FROM (select ID,max(Signal) as Signal from mytable group by ID) T1
LEFT JOIN mytable T2
ON T1.ID=T2.ID and T1.Signal=T2.Signal;

O también puedes utilizar la siguiente consulta

SELECT t0.ID,t0.Signal,t0.Station,t0.OwnerID 
FROM mytable t0 
LEFT JOIN mytable t1 ON t0.ID=t1.ID AND t1.Signal>t0.Signal 
WHERE t1.ID IS NULL;
select a.id, b.signal, a.station, a.owner from 
mytable a
join 
(SELECT ID, MAX(Signal) as Signal FROM mytable GROUP BY ID) b
on a.id = b.id AND a.Signal = b.Signal 
SELECT * FROM StatusTable
WHERE Signal IN (
    SELECT A.maxSignal FROM
    (
        SELECT ID, MAX(Signal) AS maxSignal
        FROM StatusTable
        GROUP BY ID
    ) AS A
);

seleccione  carné de identidad,  max_signal,  propietario,  ID_PROPIETARIO DE (   seleccionar *, rango () sobre (partición por orden Identificación por desc señal) como max_signal de la mesa ) donde max_signal = 1;

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