문제

좋아, 다음과 같은 테이블이 있습니다.

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()를 사용해 보았더니 각 레코드마다 Station과 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에서는 악화되지 않습니다.

이 문제에 대한 여러 가지 접근법 (표준 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의 최대 신호 값을 식별합니다.조인은 이를 기본 테이블의 해당 데이터 행과 결합합니다.

참고:특정 ID에 대해 모두 동일한 신호 강도를 갖고 해당 강도가 MAX()인 항목이 여러 개 있는 경우 해당 ID에 대한 여러 출력 행을 얻게 됩니다.


Solaris 10에서 실행되는 IBM Informix Dynamic Server 11.50.FC3에 대해 테스트되었습니다.

+ 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) 이 쿼리를 크게 향상시킬 것입니다.

우리는 Self Join을 사용하여 할 수 있습니다

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, 소유자, 소유자, (select *, rank () over (신호 desc에 의한 분할)에서 max_signal로서의 max_signal)에서 max_signal = 1을 선택하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top