简单查询抓斗最高值为每个ID
-
09-09-2019 - |
题
行我有这样的表:
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;