2017-03-01 1 views
2

다음과 같은 데이터 세트가 있습니다. example data set.max() 함수를 사용하여 SQL/postgreSQL을 사용하여 가장 최근의 행을 검색하는 방법

하나의 도메인 아래에 여러 명의 사용자가 있습니다. email_domain 당 하나의 행만 필요하며 행은 max (last_login) 값과 일치해야합니다. 즉, 같은 도메인의 모든 사용자 중에서 마지막으로 로그인 한 email_domain의 사용자 만 로그인하면됩니다.

필자과 같은 쿼리를 시도이

select * 
FROM 
(
select LOWER(SUBSTRING(ua.email FROM POSITION ('@' IN ua.email) + 1)) AS email_domain, last_login, last_name, first_name, email, phone 
from user_with_address ua 
order by email_domain 
) as A 
group by email_domain, last_login, last_name, first_name, email, phone 
having last_login = max(last_login) 
order by email_domain 

난 아직도 내가 잘못 뭐하는 거지 각 전자 메일 도메인에 대한 여러 값을 가진 목록을 얻을? 도와주세요.

면책 조항 : 본인은 기본적인> SQL에 대한 지식이 있습니다.

+0

last_login으로 그룹화하고 있습니다. 아마도 max (last_login)을 선택하고 그룹화하지 않으시겠습니까? 또한 이름, 이메일, 전화 번호 등으로 그룹화하면 도메인에서 레코드가 분리됩니다. –

답변

2

사용 distinct on()

select distinct on (email_domain) * 
FROM (
    select lower(split_part(email, '@', 2)) AS email_domain, 
     last_login, 
     last_name, 
     first_name, 
     email, 
     phone 
    from user_with_address 
) as A 
order by email_domain, last_login desc; 

나는 또한 패트릭의 이메일에서 도메인을 추출하는 표현을 단순화하기 위해 제안을 통합.

+0

감사합니다. 이것은 last_login desc로 정렬하고 distinct를 사용하여 첫 번째 행을 선택하여 완벽하게 작동했습니다. –

0

하나의 옵션은 ROW_NUMBER()을 사용하고 동일한 이메일 도메인 레코드의 각 그룹에 대한 최신 로그인 기록을 유지하는 것입니다.

SELECT t.email_domain, t.last_login, t.last_name, t.first_name, t.email, t.phone 
FROM 
(
    SELECT a.*, 
      ROW_NUMBER() OVER (PARTITION BY a.email_domain ORDER BY a.last_login DESC) rn 
    FROM 
    (
     SELECT LOWER(SUBSTRING(ua.email FROM POSITION ('@' IN ua.email) + 1)) AS email_domain, 
       last_login, last_name, first_name, email, phone 
     FROM user_with_address ua 
    ) a 
) t 
WHERE t.rn = 1 
ORDER BY t.email_domain 

실제로 전자 메일 도메인을 계산하는 코드를 반복하지 않아도되도록 여기에 두 번 서브 쿼리합니다. 그런 경우가 아니라면 하위 쿼리 하나만으로이 작업을 수행 할 수있었습니다. 여기에 하나의 하위 쿼리를 사용할 수 있지만 쿼리를 읽는 것이 약간 어려울 수 있습니다.

+0

'substring (ua.email FROM position (...) + 1)'대신'split_part (ua.email, '@', 2)'를 사용하십시오. – Patrick

+0

감사합니다. 이것은 더 이해하기 쉽고 더 간단합니다. –

0

나는 Tim Biegeleisen의 답변을 좋아하지만, 이것은 SQL 간단합니다. 성능 차이에 대해서는 잘 모릅니다.

select 
    LOWER(SUBSTRING(ua.email FROM POSITION ('@' IN ua.email) + 1)) AS email_domain, 
    last_login, 
    last_name, 
    first_name, 
    email, 
    phone 
from user_with_address ua 
where last_login = (select max(last_login) 
        from user_with_address ua2 
        where LOWER(SUBSTRING(ua.email FROM POSITION ('@' IN ua.email) = 
          LOWER(SUBSTRING(ua2.email FROM POSITION ('@' IN ua2.email)) 
order by email_domain; 
관련 문제