行我有这样的表:

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

这是所有在同一天。我只需要查询为每个ID返回最大信号:

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

我尝试使用MAX()和聚合与站和OWNERID对于每个记录不同弄乱。我需要做一个JOIN?

有帮助吗?

解决方案

这样的?与本身加入您表,并且排除针对其较高的信号被发现的行。

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
)

这会列出每个最高的信号的一行,所以有可能是每个ID的多个行。

其他提示

您正在做一个组地最大/最小操作。这是一个常见的陷阱:感觉的东西,应该是很容易做到,但在SQL它aggravatingly不是

有许多方法(包括标准ANSI和供应商特定的)到这个问题,其中大部分是在许多情况下次优的。当多行共享相同的最大值/最小值有些会给你多行;有些则不会。以及与少数群体的表中的某些工作;其它的是用于与每组较小的行组的更大数目的更有效。

下面的一些常见的(MySQL的偏置,但一般适用的话)的讨论。就个人而言,如果我知道有没有多个最大值(或不关心,让他们)我常常倾向于空左自加入方法,我会后作为没有其他人尚未:

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;

在经典SQL-92(未使用由Quassnoi使用的OLAP操作),那么就可以使用:

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;

(未选中的语法;假设你的表是 'T')

在FROM子句子查询标识每个ID的最大信号值;联接结合了与从主表中的相应数据行。

NB:如果有几个条目为特定的ID都具有相同的信号强度,并且强度为MAX(),那么你将得到几个输出行对于ID


测试针对IBM的Informix动态服务器11.50.FC3

在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

我命名的表Signal_Info此测试 - 但它似乎产生正确的答案。 这只能说明有支持符号至少一个DBMS。不过,我有点惊讶的是MS SQL Server不 - ?您正在使用哪个版本


它从来没有停止多久SQL问题不表名称被提交给我惊喜。


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

这将返回一个行即使有MAX(signal)的重复对于给定的ID

上具有(id, signal)索引会大大提高该查询。

我们可以做到使用自加入

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;

或者你也可以使用下面的查询

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

选择  ID,  max_signal,  所有者,  OWNERID FROM(   选择*,过(分区由ID,以便通过信号DESC)秩(),如从表max_signal ) 其中max_signal = 1;

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top