简单的查询来获取每个ID的最大值
好的,我有一张这样的桌子:
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是不同的每个logging。 我需要join吗?
像这样的东西? join你自己的表格,排除find更高信号的行。
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中,它加重不了。
对于这个问题,有许多方法(包括标准的ANSI和供应商特定的),其中大部分在许多情况下是次优的。 当多行共享相同的最大值/最小值时,有些会给你多行; 有些不会。 有些小组在桌子上工作得很好; 其他人对于每个组中具有较小行数的较大数量的组更有效。
以下是一些常见的讨论 (MySQL有偏见但通常适用)。 就个人而言,如果我知道没有多个最大值(或者不关心如何得到它们),我经常倾向于null-left-self-join方法,
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的最大信号值; 连接将它与主表中相应的数据行组合在一起。
注意:如果某个特定ID有多个条目都具有相同的信号强度,并且强度是MAX(),那么您将为该ID获得多个输出行。
针对在Solaris 10上运行的IBM Informix Dynamic Server 11.50.FC3进行testing:
+ 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
我为这个testing命名了Signal_Info表,但它似乎产生了正确的答案。 这只显示至less有一个支持符号的DBMS。 但是,我有点惊讶,MS SQL Server不 – 你使用的是哪个版本?
从来没有停止惊讶我多less提交没有表名称的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 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
这将返回一行,即使有一个给定的ID
的MAX(signal)
重复。
(id, signal)
上的索引将大大改善此查询。
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 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 * FROM StatusTable WHERE信号IN( SELECT A.maxSignal FROM ( SELECT ID,MAX(Signal)AS maxSignal 从StatusTable GROUP BY ID ) 作为一个 );