Pergunta

OK eu tenho uma tabela 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

Isso é tudo para o mesmo dia. Eu só preciso a consulta para retornar o sinal máximo para cada ID:

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

Eu tentei usar MAX () e os messes de agregação com a estação e OwnerID ser diferente para cada registro. Preciso fazer um JOIN?

Foi útil?

Solução

Algo como isso? Junte-se a sua mesa com ele mesmo, e excluir as linhas para as quais foi encontrado um sinal maior.

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
)

Este iria listar uma linha para cada sinal mais alto, então pode haver várias linhas por id.

Outras dicas

Você está fazendo uma operação máximo / mínimo grupo-wise. Esta é uma armadilha comum:. Sente como algo que deve ser fácil de fazer, mas em SQL que aggravatingly não é

Há uma série de abordagens (tanto ANSI padrão e-específico do fornecedor) para este problema, a maioria dos quais são sub-óptima em muitas situações. Alguns lhe dará várias linhas quando mais de um ações de linha o mesmo valor máximo / mínimo; alguns não. Alguns trabalham bem em mesas com um pequeno número de grupos; outros são mais eficientes para um maior número de grupos com filas menores por grupo.

Aqui está uma discussão de alguns dos mais comuns (MySQL-tendenciosa mas geralmente aplicável). Pessoalmente, se eu sei que não há maxima múltipla (ou não se preocupam com começá-los) eu muitas vezes tendem para o método nulo deixou-autojunção, que vou postar como ninguém mais ainda:

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;

No SQL-92 clássica (não usar as operações OLAP utilizados por Quassnoi), então você pode usar:

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;

(sintaxe Desmarcado;. Assume a sua mesa está 't')

A sub-consulta no DE identifica cláusula o valor máximo do sinal para cada id; a juntar-se combina isso com a linha de dados correspondente da tabela principal.

NB:. Se há várias entradas para um ID específico que todos têm a mesma intensidade do sinal e que a força é o MAX (), então você vai ter várias linhas de saída para esse ID


Testado contra a IBM Informix servidor 11.50.FC3 dinâmica em execução no 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

I chamado a mesa Signal_Info para este teste - mas parece para produzir a resposta certa. Isso só mostra que há pelo menos um DBMS que suporta a notação. No entanto, estou um pouco surpreso que o MS SQL Server não - qual versão você está usando


Ela nunca deixa de me surpreender quantas vezes SQL perguntas são submetidos, sem nomes de tabela.


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

Isto irá devolver uma linha, mesmo se houver duplicatas de MAX(signal) para um determinado ID.

Ter um índice em (id, signal) irá melhorar significativamente esta consulta.

Nós podemos fazer usando auto join

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;

Ou você também pode usar a seguinte 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
);

selecione Eu iria, max_signal, proprietário, ownerId A PARTIR DE ( seleccionar *, posto () ao longo de (partição por ordem ID por desc sinal), como a partir da tabela max_signal ) onde max_signal = 1;

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top