Question

OK J'ai une table comme ceci:

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

Ceci est tout pour le même jour. J'ai juste besoin de la requête pour renvoyer le signal max pour chaque ID:

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

J'essayé d'utiliser MAX () et l'agrégation Messes avec la station et OwnerID étant différente pour chaque enregistrement. Est-ce que je dois faire JOIN?

Était-ce utile?

La solution

Quelque chose comme ça? Joignez-vous à votre table avec elle-même, et d'exclure les lignes pour lesquelles un signal plus élevé a été trouvé.

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
)

Cette liste serait une ligne pour chaque signal le plus élevé, donc il peut y avoir plusieurs lignes par id.

Autres conseils

Vous faites une opération maximum / minimum sage groupe. Ceci est un piège commun. Il se sent comme quelque chose qui devrait être facile à faire, mais dans SQL il est aggravatingly pas

Il y a un certain nombre d'approches (à la fois la norme ANSI et spécifique au fournisseur) à ce problème, dont la plupart sont sous-optimaux dans de nombreuses situations. Certains vous donneront plusieurs lignes lorsque plus d'une ligne partage la même valeur maximum / minimum; d'autres non. Certains fonctionnent bien sur les tables avec un petit nombre de groupes; d'autres sont plus efficaces pour un plus grand nombre de groupes avec de plus petites lignes par groupe.

Voici une discussion de quelques-unes des plus courantes (MySQL biaisées mais généralement applicables). Personnellement, si je sais il n'y a pas plusieurs maxima (ou ne se soucient pas de les obtenir) Je tends souvent vers la méthode null-gauche-autojointure, que je posterai comme personne d'autre n'a encore:

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;

Dans classique SQL-92 (ne pas utiliser les opérations OLAP utilisées par Quassnoi), vous pouvez utiliser:

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;

(syntaxe non cochée;. Suppose que votre table est 't')

Le sous-requête dans la clause FROM identifie la valeur maximale du signal pour chaque ID; la jointure se combine avec celle de la ligne de données correspondante de la table principale.

NB:. S'il y a plusieurs entrées pour un ID spécifique qui ont tous la même intensité du signal et que la force est le MAX (), vous obtiendrez plusieurs lignes de sortie pour cet ID


Testé contre IBM Informix Dynamic Server 11.50.FC3 en cours d'exécution sur 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

Je l'ai appelé la table Signal_Info pour ce test - mais il semble produire la bonne réponse. Cela montre seulement qu'il ya au moins un SGBD qui prend en charge la notation. Cependant, je suis un peu surpris de constater que MS SQL Server ne - quelle version vous utilisez


Il ne cesse de me surprendre comment sont soumis souvent des questions SQL sans noms de table.


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

retourne une ligne, même s'il y a des doublons de MAX(signal) pour un ID donné.

Avoir un index sur (id, signal) améliorera grandement cette requête.

Nous pouvons le faire en utilisant l'auto rejoindre

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;

Vous pouvez également utiliser la requête suivante

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

sélectionnez  id,  max_signal,  propriétaire,  OWNERID DE (   sélectionner *, le rang () plus (partition par ordre d'id par le signal desc) comme max_signal de la table ) où max_signal = 1;

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top