Frage

OK Ich habe eine Tabelle wie folgt aus:

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

Das ist alles für den gleichen Tag. Ich brauche nur die Abfrage den max Signal für jede ID zurück:

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

Ich habe versucht, MAX () verwendet und die Aggregation vermasselt mit der Station und OwnerID für jeden Datensatz anders zu sein. Brauche ich einen JOIN?

zu tun
War es hilfreich?

Lösung

So etwas wie das? Verbinden Sie Ihre Tabelle mit sich selbst, und schließen Sie die Zeilen, für die ein höheres Signal gefunden wurde.

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
)

Dies würde für jedes höchstes Signal eine Zeile Liste, so dass es möglicherweise mehr Zeilen pro-ID sein.

Andere Tipps

Sie machen einen gruppenweise Maximum / Minimum-Betrieb. Dies ist eine gemeinsame Falle:. Es fühlt sich an wie etwas, das einfach zu tun sein sollte, aber in SQL ist es aggravatingly nicht

Es gibt eine Reihe von Ansätzen (sowohl Standard ANSI und herstellerspezifisch) für dieses Problem, die meisten davon in vielen Situationen suboptimal sind. Einige werden Sie mehrere Zeilen geben, wenn mehr als eine Zeile die gleiche Maximum / Minimum-Wert teilt; manche nicht. Einige arbeiten auch auf den Tischen mit einer kleinen Anzahl von Gruppen; andere sind effizienter für eine größere Anzahl von Gruppen mit kleineren Zeilen pro Gruppe.

Hier ist eine Diskussion einige der allgemeinsten (MySQL-voreingenommen, sondern allgemein anwendbar). Persönlich, wenn ich weiß, gibt es keine mehrere Maxima (oder kümmern sich nicht um sie bekommen) Ich neige dazu, oft in Richtung Null-links-Self-Join-Methode, die ich als niemand veröffentlichen werde sonst noch:

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;

In der klassischen SQL-92 (nicht die OLAP-Operationen von Quassnoi verwendet verwenden), dann können Sie:

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;

(Ungeprüft Syntax;. Nimmt an dem Tisch ist 't')

Die Unterabfrage in der FROM-Klausel gibt den maximalen Signalwert für jede id; die Verbindung kombiniert, die mit der entsprechenden Datenzeile von der Haupttabelle.

. NB: wenn es mehr Einträge für eine bestimmte ID, die alle die gleiche Signalstärke haben und dass Stärke ist der MAX (), dann werden Sie für diese ID mehrere Ausgabezeilen erhalten


Getestet gegen IBM Informix Dynamic Server 11.50.FC3 läuft auf 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

Ich nannte die Tabelle Signal_Info für diesen Test - aber es scheint, die richtige Antwort zu produzieren. Dies zeigt nur, dass es mindestens ein DBMS ist, die die Notation unterstützt. Aber ich bin ein wenig überrascht, dass MS SQL Server nicht - welche Version verwenden Sie


Es hört nie auf, mich zu überraschen, wie oft SQL Fragen ohne Tabellennamen vorgelegt werden.


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

Dies wird eine Zeile zurückgeben, auch wenn es Duplikate von MAX(signal) für einen bestimmten ID sind.

einen Index für (id, signal) Having wird diese Abfrage erheblich verbessern.

Wir können selbst tun mit beitreten

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;

Sie können aber auch die folgende Abfrage verwenden

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

wählen  Ich würde,  max_signal,  Inhaber,  ownerId VON (   select *, Rang () über (Partition-ID, um durch das Signal ab) als max_signal aus der Tabelle ) wo max_signal = 1;

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top