😵 ~23.11.10

0817 | Oracle Join, Union, 게시글 목록 만들기 & 두번째 페이지 추출

unikue 2023. 8. 18. 17:22

✅ Oracle Join

select * from member m, notice n; 으로 하면 cross join이 된다

 

 

✅ Union

: join은 컬럼확장을 위해 컬럼을 붙이는 것

: union은 레코드를 확장하는 것 ▶ 같은 테이블일지라도 조건을 동일하게 하여 합칠 수 있고, 다른 테이블도 조건을 맞춰서 합칠 수 있다.

  • 컬럼의 수가 동일하게 정해져있어야 한다
  • 관계는 아무상관 없음.

 

-- 한 테이블 안에서는 유니온을 안쓰고 그냥 조회하는게 가능하다. 하지만 다른 카테고리와 레코드를 합친다면?
select id, title from notice where length(title) between 4 and 5;
select id, title from notice where length(title) in (4,5);
select id, name, 'category' src from category where length(name)=2
union
select id, title, 'notice' src from notice where length(title)=5;
-- 'string' 별칭 으로 기재하면 고정값으로 좌르륵 들어감

 

 

 

 

 

#️⃣ Union 연산

select name from category where length(name)=2
intersect
select title from notice where length(title)=2;

👉 중복 값이 출력될 때 앞의 테이블에 있는 속성명으로 출력됨!

 

 

 

✅ 데이터 모델링 기초

👉 어떤 테이블에 어떤 데이터를 관리해야 하는가?

예) 화면에서 보이는 좋아요는 메뉴와 같은 테이블에 있는게 아니다. 메뉴에는 포함되지 않지만 자식테이블로 들어가서 같은 화면에 들어간다. 이 구조를 짜는 것.

 


#️⃣  필요한 컬럼을 늘리는 방법

1. 서브쿼리 사용 - 셀렉트 할때마다 테이블을 쿼리하므로 성능이 안좋아질 수 있음
2. 컬럼을 늘려서 만들어냄 (조인) - 관계가 있는 상태에서 부모 컬럼을 가져올때는 조인이 더 알맞음
👉 조인을 통해 합친 다음에 필터링을 통해서 모양을 만들어낸다

 

 


 

 

✅ 원하는 목록 만들기

Q.  공지사항(notice) 정보에 회원(member)의 이름을 붙여서 출력하기

select rownum id, n.id originId, n.title, n.reg_member_id as WRITER_ID, m.name WRITER_NAME 
from notice n left join member m on n.reg_member_id=m.id;

-- 이중정렬을 적용한다면? > 같은 WRITER_ID 내에서 n.id가 적용되므로 원하는 넘버링의 형태로 나오지 않는다
select n.id originId, n.title, n.reg_member_id as WRITER_ID, m.name WRITER_NAME 
from notice n left join member m on n.reg_member_id=m.id order by WRITER_ID,n.id;

👉  조인을 통해 새로운 테이블을 만든 후 원하는 테이블을 뽑아낸다. 이때 WRITER_ID도 정렬하고 rownum도 순서대로 정렬하고 싶다면 정렬한 데이터를 기반으로 원하는 목록을 뽑아낸다 (=한단계 더 위로 올라가야 함)

 

select rownum id, title, reg_member_id as WRITER_ID, name WRITER_NAME 
from (select * from notice n left join member m on m.id = n.reg_member_id order by n.reg_member_id)
where reg_member_id is not null;

 

 

 

 

Q. 댓글의 수를 카운트하는 컬럼을 추가하기

select n.id, n.title, n.reg_member_id as WRITER_ID, m.name WRITER_NAME,count(c.id)as CMT_COUNT -- 댓글의 수를 카운트하므로 c.id
    from (notice n 
    left join member m on n.reg_member_id=m.id -- 얘는 앞의 노티스가 조인의 기준
    left join "COMMENT" c on c.NOTICE_ID=n.id)   -- 얘가 보는 기준은 앞의 전체가 조인의 기준
    group by ( n.id, n.title, n.reg_member_id , m.name) -- select에서 ~별로 뽑아내고 싶다면 그 전체가 group by에 들어가 있어야 한다
    ;

 

 

 

 

 

+ 기본 목록에 정렬, 필터링을 추가해야 한다

 

 

 

 


 

 

 

Q.  1페이지 뽑기

select rownum, t.*
    from (select n.id, n.title, n.reg_member_id as WRITER_ID, m.name WRITER_NAME,count(c.id)as CMT_COUNT
        from (notice n 
        left join member m on n.reg_member_id=m.id
        left join "COMMENT" c on c.NOTICE_ID=n.id)
        group by ( n.id, n.title, n.reg_member_id , m.name)
    )t
    where rownum between 1 and 10;

from ▶ (계층구조시 connect by) ▶ where ▶ group by ▶having ▶select ▶ order by (실행순서)

👉  이렇게하면 1페이지는 뽑을수있는데 2페이지는 나오기 어려움. 결과에 rownum을 붙여서 1~10만 select했기 때문

 

 

 

 

Q. 2페이지 뽑기

✔ 잘못 뽑은 코드

select t.*
    from (select rownum num, n.id, n.title, n.reg_member_id as WRITER_ID, m.name WRITER_NAME,count(c.id)as CMT_COUNT
        from (notice n 
        left join member m on n.reg_member_id=m.id
        left join "COMMENT" c on c.NOTICE_ID=n.id)
        group by (rownum, n.id, n.title, n.reg_member_id , m.name)
    )t
where num between 11 and 20;

👉 group by 에 rownum을 넣게 되면 구문오류는 없지만 select했을시에 rownum대로 묶인게 출력되면서 데이터가 좀 섞이게 됨.....▶ 한단계 위에서 rownum을 붙여줘야 함

 

 

 

제대로 뽑은 코드

select * 
    from (select rownum num, t.*
        from (select n.id, n.title, n.reg_member_id as WRITER_ID, m.name WRITER_NAME,count(c.id)as CMT_COUNT
            from (notice n 
            left join member m on n.reg_member_id=m.id
            left join "COMMENT" c on c.NOTICE_ID=n.id)
            group by (n.id, n.title, n.reg_member_id , m.name)
            )t
        )
        where num between 11 and 20;

👉 최종 데이터에 rownum을 붙이고 그 데이터에 where문을 넣는다