4 Ways to Join Only The First Row in SQL

 

For today’s daily report, we need a list of users and the most recent widget each user has created. We have a users table and a widgets table, and each user has many widgets. users.id is the primary key on users, and widgets.user_id is the corresponding foreign key in widgets.

To solve this problem, we need to join only the first row. There are several ways to do this. Here are a few different techniques and when to use them.

Use Correlated Subqueries when the foreign key is indexed

Correlated subqueries are subqueries that depend on the outer query. It’s like a for loop in SQL. The subquery will run once for each row in the outer query:

select * from users join widgets on widgets.id = (
    select id from widgets
    where widgets.user_id = users.id
    order by created_at desc
    limit 1
)

Notice the where widgets.user_id = users.id clause in the subquery. It queries the widgets table once for each user row and selects that user’s most recent widget row. It’s very efficient if user_id is indexed and there are few users.

Use a Complete Subquery when you don’t have indexes

Correlated subqueries break down when the foreign key isn’t indexed, because each subquery will require a full table scan.

In that case, we can speed things up by rewriting the query to use a single subquery, only scanning the widgets table once:

select * from users join (
    select distinct on (user_id) * from widgets
    order by user_id, created_at desc
) as most_recent_user_widget
on users.id = most_recent_user_widget.user_id

This new subquery returns a list of the most recent widgets, one for each user. We then join it to the users table to get our list.

We’ve used Postgres’ DISTINCT ON syntax to easily query for only one widget per user_id. If your database doesn’t support something like DISTINCT ON, you have two options:

Use Nested Subqueries if you have an ordered ID column

In our example, the most recent row always has the highest id value. This means that even without DISTINCT ON, we can cheat with our nested subqueries like this:

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

select * from users join (
    select * from widgets
    where id in (
        select max(id) from widgets group by user_id
    )
) as most_recent_user_widget
on users.id = most_recent_user_widget.user_id

We start by selecting the list of IDs repreenting the most recent widget per user. Then we filter the main widgets table to those IDs. This gets us the same result as DISTINCT ON since sorting by id and created_at happen to be equivalent.

Use Window Functions if you need more control

If your table doesn’t have an id column, or you can’t depend on its min or max to be the most recent row, use row_number with a window function. It’s a little more complicated, but a lot more flexible:

select * from users join (
    select * from (
        select *, row_number() over (
            partition by user_id
            order by created_at desc
        ) as row_num
        from widgets
    ) as ordered_widgets
    where ordered_widgets.row_num = 1
) as most_recent_user_widget
on users.id = most_recent_user_widget.user_id
order by users.id

The interesting part is here:

select *, row_number() over (
    partition by user_id
    order by created_at desc
) as row_num
from widgets

over (partition by user_id order by created_at desc specifies a sub-table, called a window, per user_id, and sorts those windows by created_at desc. row_number() returns a row’s position within its window. Thus the first widget for each user_id will have row_number 1.

In the outer subquery, we select only the rows with a row_number of 1. With a similar query, you could get the 2nd or 3rd or 10th rows instead.

In a future post we’ll go deeper on window functions and how they can make queries like this one even more powerful!

 

[출처] https://www.periscopedata.com/blog/4-ways-to-join-only-the-first-row-in-sql

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
공지 오라클 기본 샘플 데이터베이스 졸리운_곰 2014.01.02 86852
공지 [SQL컨셉] 서적 "SQL컨셉"의 샘플 데이타 베이스 SAMPLE DATABASE of ORACLE 가을의 곰을... 2013.02.10 79152
공지 [G_SQL] Sample Database 가을의 곰을... 2012.05.20 95891
26 감석분석 작업 로그 : 감성분석(Sentiment Analysis) - 깔끔한 텍스트 방식(tidytext) : xwMOOC 자연어 처리 졸리운_곰 2019.12.24 1244
25 '애자일과 데이터 관리의 결합'··· '데이터옵스'의 정의와 주요 기술 file 졸리운_곰 2019.11.17 1684
24 데브옵스와 분석의 결합··· ‘데이터옵스’를 아시나요? file 졸리운_곰 2019.11.17 1242
23 데이터옵스(DATAOPS) 란 무엇일까? file 졸리운_곰 2019.11.17 1638
22 데이터옵스는 단순히 데이터에 대한 데브옵스가 아님니다. DataOps is NOT Just DevOps for Data file 졸리운_곰 2019.11.17 1639
21 R에서 파이썬까지…데이터과학 학습 사이트 8곳 file 졸리운_곰 2019.04.21 1759
20 [통계] prediction VS forecast file 졸리운_곰 2019.04.03 1583
19 forecast 와 prediction의 차이를 아시나요? 졸리운_곰 2019.04.03 899
18 10분만에 끝내는 데이터분석 file 졸리운_곰 2019.04.03 1867
17 처음으로 케글 데이터분석에 도전하기 : Competing on kaggle.com for the First Time file 졸리운_곰 2019.01.27 4412
16 데이터 과학자가 갖춰야 할 5가지 스킬셋 file 졸리운_곰 2018.11.11 1377
15 데이터 사이언스 괜찮은 강의들 리스트 1 file 졸리운_곰 2018.11.11 2470
14 데이터 사이언스 학습 안내 졸리운_곰 2018.11.11 1671
13 Prophet: Automatic Forecasting Procedure 자동 예측 프로시져 프로그램 /데이터분석 / 데이터 과학 file 졸리운_곰 2018.09.04 1316
12 데이터 분석 어디에 집중할 것인가? 가장 먼저 실험에 집중하라 file 졸리운_곰 2018.02.06 1404
11 빅데이터 융합기획전문가 1기 교육 표창장 file 졸리운_곰 2018.01.03 1317
10 빅 데이터 기획에 대한 이해 file 졸리운_곰 2017.12.09 2024
9 분야별 빅데이터 애널리틱스 적용 사례 및 성공의 비결 file 졸리운_곰 2017.12.08 2161
8 하둡 에코시스템을 활용한 Hybrid DW 구축 사례 file 졸리운_곰 2017.12.08 2005
7 gmail 수신 메일로 워드클라우드 생성 : Creating a gmail wordcloud 졸리운_곰 2017.11.20 1893
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED