게시글
질문&답변
2024.05.14
Date 강의 / leetcode 1321 질문
승렬님 안녕하세요:) 참신한 방법으로 풀어주셨는데요! 먼저 승렬님께서 간과했던 부분을 말씀드리겠습니다. 승렬님처럼 작성하면 2019-01-08 데이터가 포함됩니다. 데이터는 2019-01-04부터 시작하는데, 7일치의 데이터가 안 만들어지기 때문에 2019-01-08 데이터는 포함되면 안됩니다. (그런 의미에서 2019-01-09도 들어가면 안되는데, 승렬님 코드로 Output에 포함됨) 하지만 이렇게 잘못 포함된 이유는 having count(amount) >= 7 로 작성하셨기 때문입니다. 그러면 160부터 90까지의 amount 데이터가 7개 존재하기 때문에, 2019-01-08 데이터도 조건에 포함되어서 들어가게 된 것입니다. (사진) 그럼 승렬님과 비슷한 로직으로 올바르게 작성하려면 아래와 같이 작성하면 됩니다. (having절을 having count(distinct a.visited_on) = 7 로 바꿨습니다.) select b.visited_on, sum(amount) as amount, round(sum(a.amount) /7, 2) as average_amount from customer a inner join ( select distinct date_sub(visited_on, interval 6 day) as week_before, visited_on from customer ) b on a.visited_on between b.week_before and b.visited_on group by b.visited_on having count(distinct a.visited_on) = 7 order by b.visited_on; 이렇게 보면 헷갈릴 수 있으니 select * inner join order by까지만 작성 후 풀어헤쳐보면 아래와 같이 결과가 나올텐데요. 여기서 2019-01-08과 같은 데이터는 포함하지 않게 하기 위해서, having절에 distinct a.visited_on의 개수가 7개가 되어야 한다는 조건을 추가해서 제거합니다. (사진) 혹시 읽으시고 이해가 안가면, 편하게 질문 다시 주셔요 :)
- 1
- 1
- 27
질문&답변
2024.05.07
cross join, full join강의 / leetcode 1280번 문제 질문드립니다
승렬님 안녕하세요:) 늘 참신한 질문을 주셔서 감사합니다. leetcode: https://leetcode.com/problems/students-and-examinations/description/ 승렬님의 질문이 위의 코드 ( e.subject_name -> 정답 코드)와 아래 코드( a.subject_name -> 오답 코드)의 차이가 무엇이냐로 이해했는데요. (사진) (사진) 이해를 위해 아래와 같이 데이터를 좀더 풀어봤습니다. (select *로 확인) (사진) 왼쪽 노란색 박스는 a temp table에서, 오른쪽 노란색 박스는 e temp table에서 온 결과입니다. 참고로 초록색 박스의 row가 왜 3개인지 말씀 드리면, a temp table에서는 (1, Alice, Math) 조합이 1개이지만, e temp table에서는 (1, Math) 조합이 3개이므로 조인하는 과정에서 3개로 뻥튀기된 것입니다. 승렬님의 질문은 분홍색 박스를 확인하면 되는데요. a temp table에서는 늘 subject_name이 들어있습니다. (분홍색 박스에서 Physics 존재) 반면 e temp table에서는 Examinations table에 없다면 조인할 데이터가 없으므로 null로 나타날 것입니다. null 데이터는 count 자체가 성립이 안되기 때문에, count(null)=0이 됩니다. 그렇기 때문에 우리의 정답 코드처럼 count(e.subject_name) 을 하면 0으로 나오는 것입니다. 반면 Physics는 count를 할 수 있기 때문에, count(Physics)=1이 됩니다. 그렇게 때문에 오답 코드 처럼 count(a.subject_name) 을 하면 늘 1로 나오는 것입니다. 읽어보시고 이해 안가는 부분이 있으시면, 추가 질문 부탁드립니다:)
- 1
- 1
- 54
질문&답변
2024.05.02
not In강의 / leetcode 1978 질문 드립니다
승렬님 안녕하세요:) leetcode 문제: https://leetcode.com/problems/employees-whose-manager-left-the-company/description/ 먼저, 이해하기 쉽게 Employees 테이블을 전체 조회하면 아래처럼 나옵니다. (사진) 그 다음에 서브쿼리를 쓰지 않고 바로 not in으로 비교하면, row별 manager_id와 employee_id를 비교 하게 됩니다. (사진) 이건 마치 manager_id와 employee_id가 서로 다른 row를 조회하는 셈이 되는데요. 전체 Employees 테이블 조회했을 때 나왔던 manager_id=null이 여기서 나오지 않은 이유는, null은 특정 값과 비교자체가 안되기 때문입니다. (숫자 '0'이 '4'와 다르다라고 말할 수는 있어도, '없다'(=null)과 '4'와 같다, 다르다라고 비교 자체가 성립되지 않습니다) (사진) 하지만 이렇게 서브쿼리를 쓴다면, 이제 더이상 row별로 manager_id와 employee_id가 다른지 비교하는게 아니라, manager_id가 ( 3, 12, 13, 1, 9, 11)이 아니기만 하면 된다라는 조건으로 바뀝니다. 그리고 이게 실제 문제를 풀려고 우리가 의도했던 로직이 됩니다. select employee_id from Employees where salary (사진) 읽으시고 추가 궁금한 부분 있으시면, 언제든지 질문 주세요:)
- 1
- 1
- 50
질문&답변
2024.04.14
South Superstore 수업 자료 파일 오류
2-1. 선영님 혹시 Tableau Public이 아닌, Tableau Desktop 사용 중이실까요? Tableau Desktop 버전을 업그레이드 시킨 후에, 그 전에 생성한 workbook을 열려고 할 때 -> 연결된 data source(엑셀)가 연결이 안될 때도 있다고 합니다. 일단 선영님께서 이러한 상황이셨는지 확인 부탁드립니다. (사진) https://help.salesforce.com/s/articleView?id=001471860&type=1 2-2. 제가 첨부한 'South-Superstore.xlsx' 엑셀은 아래 github에서 다운로드하였습니다. 해당 엑셀은 row 개수가 1000개 정도이여서 가벼워서 빠르기 때문에 선택하였습니다. https://github.com/ARAPIL/South-Superstore/blob/master/South-Superstore.xlsx Tableau Desktop 또는 Public 프로그램에서 'Sample - Superstore.xls'를 사용할 수 있습니다. 하지만 해당 데이터들은 row 개수가 9000개 이상 넘어가서 조작하는데 느리기 때문에 사용을 지양하였습니다. (사진)
- 0
- 2
- 74
질문&답변
2024.04.14
South Superstore 수업 자료 파일 오류
선영님 안녕하세요:) 흠 이상하네요... 강의 업로드하는 란에서는 엑셀 확장자로 나오는데요. 선영님께서 말씀 주신 것처럼 저도 다운받으면 선영님처럼 다운 받아지네요. 확인하는 과정에서 다른 파일들도 이상하게 다운 받아져서 다시 일괄 업로드 하였습니다. 다시 다운 받으시면 됩니다! 제보 감사합니다. 이 부분은 인프런 팀에 제가 따로 문의해보도록 하겠습니다.
- 0
- 2
- 74
질문&답변
2024.03.29
LEETCODE - Sales Analysis 3 코드 질문드립니다.
안녕하세요 zuuzuubin 님 꼭 제 강의 아니더라도 SQL 문제 질문은 늘 환영입니다!:) 아래 풀이 보시고 이해 안가시면 재질문 부탁드립니다. 문제: https://leetcode.com/problems/sales-analysis-iii/description/ 풀이에서 DISTINCT 하나만 놓치신거였네요! Sales 테이블에 ‘This table can have duplicate rows’ 이렇게 써있는데요. 그래서 Sales 테이블에 동일한 product_id가 여러 개 포함될 수 있습니다. 풀이1: 동일한 product_id가 여러 개 있는 Sales 테이블과 Product 테이블이 inner join 하면서, 최종 결과물에 중복된 product_id가 존재할 것입니다. 그래서 최종 바깥쪽 select문에 DISTINCT를 추가하셔도 됩니다. SELECT DISTINCT P.PRODUCT_ID, P.PRODUCT_NAME FROM PRODUCT P INNER JOIN ( SELECT * FROM SALES WHERE PRODUCT_ID NOT IN ( SELECT PRODUCT_ID FROM SALES WHERE SALE_DATE '2019-03-31' ) ) N ON P.PRODUCT_ID = N.PRODUCT_ID; 풀이2: join하는 temp 테이블에서 product_id가 하나만 나오게끔, 미리 DISTINCT product_id를 처리해주셔도 됩니다. 그러면 join을 하더라도 product_id는 최종 결과물에서 하나씩만 나올 것입니다. SELECT P.PRODUCT_ID, P.PRODUCT_NAME FROM PRODUCT P INNER JOIN ( SELECT DISTINCT PRODUCT_ID FROM SALES WHERE PRODUCT_ID NOT IN ( SELECT PRODUCT_ID FROM SALES WHERE SALE_DATE '2019-03-31' ) ) N ON P.PRODUCT_ID = N.PRODUCT_ID;
- 1
- 1
- 79
질문&답변
2024.03.20
[The Latest Login in 2020] datetime 계산 관련
종훈님 안녕하세요:) 네~ 코딩테스트 문제로 나와도 통과가 될 올바른 풀이입니다. 다만, RDBMS에서 권장하는 방식은 아닌데요. 보통 검색 조건(=where조건)에 함수(예: year)를 씌우면 속도가 느려져서 권장하지 않습니다. time_stamp의 인덱스를 활용하지 못하고, full scan으로 검색하기 때문입니다. 혹시 위 내용이 이해가 안갔더라도, 걱정하지 마시고 편하게 읽고 넘어가셔도 됩니다. 코딩 테스트에서는 종훈님께서 작성하신 쿼리를 써도 문제 없습니다! 종훈님의 쿼리도 해당 SQL 파일에 업데이트 하였습니다. 질문 감사합니다. :) (참고) https://www.percona.com/blog/mysql-8-0-functional-indexes/ (사진)(사진)
- 1
- 1
- 73
질문&답변
2024.03.17
[Average Selling Price] 문제 테스트케이스 실패
종훈님 안녕하세요:) 예전에는 위 풀이로 통과가 되었는데, 이번에 새로운 테스트 케이스가 추가되어서 통과가 안되었네요. 새로운 테스트 케이스 product_id=3을 포함하기 위해서는, 말씀 주신대로 left outer join으로 진행해야 됩니다. 제보 감사합니다. 업데이트된 코드 및 설명은 강의의 수업자료에 업데이트하였습니다. 새롭게 다운받아주시기 바랍니다. 상세한 설명은 아래와 같습니다. 결과적으로는 아래의 쿼리로 진행해야 됩니다. select p.product_id, ifnull(round(sum(u.units*p.price)/sum(u.units), 2),0) average_price from Prices as p left join UnitsSold as u on p.product_id = u.product_id and u.purchase_date between p.start_date and p.end_date group by p.product_id; left join 이후에, Prices의 product_id=3은 UnitsSold와 조인할 부분이 없기 때문에, UnitsSold 부분에서는 null로 나올 것입니다. (사진) 그 뒤에 select문에서 product_id=3을 처리하기 위해서 ifnull을 사용하여 ifnull(round(sum(u.units*p.price)/sum(u.units), 2),0) 로 작성합니다. 위 정답을 떠나서 중요하게 집고 넘어가야 하는 부분은, u.purchase_date between p.start_date and p.end_date 를 where조건이 아닌, on조건에 추가해야 됩니다. join의 on조건과 where조건의 실행 순서는 다음과 같습니다. 1. on조건을 기준으로 '조인'한 후에, 2. where조건을 기준으로 '필터링' 합니다. 만약 u.purchase_date between p.start_date and p.end_date 조건을 on조건에 안쓰고, where조건에 쓰면 다음과 같이 결과가 나옵니다. (틀린 결과) on조건을 기준으로 '조인'한 후에 -> on p.product_id=u.product_id만 쓰는 과정에서 product_id=1은 2x2=4개로 뻥튀기 되고, product_id=2도 2x2=4개로 뻥튀기 됩니다. (사진) 2. where조건을 기준으로 '필터링' 합니다. -> where조건으로 필터링 되는 과정에서, 우리가 원했던 product_id=3도 필터링이 됩니다. 그러다보니 product_id=3을 포함시키려고 사용한 left outer join의 의미가 사라지게 됩니다. (사진) 결과적으로 위 쿼리는 우리가 원했던 결과가 아닌, 틀린 결과입니다. left outer join에서 on조건과 where조건을 혼용할 때 많이 발생하는 실수입니다. 1. on조건을 기준으로 '조인'한 후에, 2. where조건을 기준으로 '필터링' 하기 때문에 left outer join에서 on조건과 where조건을 잘 구분해서 작성해야 됩니다. 대신, inner join에서는 2개의 조건을 혼용해도 결과가 똑같기 때문에 신경을 덜 쓰셔도 됩니다. 혹시 위 글 읽어보시고 이해가 안가는 부분이 있으면, 다시 한번 말씀 부탁드립니다:)
- 1
- 3
- 101
질문&답변
2024.01.14
lag, leag 강의에서 game-play-analysis-iv 문제
Soiejung 님, 컬럼의 순서에 따라 정답/오답이 결정나는 것은 아니였고, right answer라고 나온 두번째 코드는 test case를 모두 통과해서 옳은 정답으로 우연히 나온 것입니다. wrong answer라고 나온 첫번째 코드 기준으로 설명 드리겠습니다. 일단 Soiejung님께서 첨부해주신 코드 중 LAG(event_date) OVER (ORDER BY player_id) AS prev_date 가 아닌, LAG(event_date) OVER (ORDER BY player_id, event_date) AS prev_date 로 작성해야 됩니다. (강의 코드 기준) 그래야지 아래 그림처럼, 해당 player_id의 직전 event_date가 순서대로 나옵니다. (사진) 다만, 제가 강의에서 간과했던 부분이 prev_id도 LAG(player_id) OVER (ORDER BY player_id, event_date) AS prev_id 로 ORDER BY event_date를 추가해야 됩니다. prev_id에 ORDER BY event_date를 추가하지 않는다면, 아래 그림처럼 prev_date와 동일하게 null로 찍혀야 되는 row가 서로 달라지게 됩니다. (사진) 따라서 prev_date처럼, prev_id에도 동일하게 ORDER BY event_date를 추가해줘야 합니다. 그럼 아래처럼 동일한 row에 대해서 null로 찍히게 될 것입니다. (사진) 따라서 Soiejung 님께서 2번째 코드로 right answer라고 나온 부분은 우연히 모든 test case를 통과해서 맞은 것처럼 나왔지만 실제로 틀린 코드입니다. 1번째 코드의 prev_id와 prev_date를 올바르게 수정해서 다시 돌린다면, right answer로 나오게 될 것입니다. 추후 prev_id 코드에 대해서 강의 수정 진행하도록 하겠습니다. 읽어보시고, 이해가 안가신다면 편하게 다시 질문 부탁드립니다! :)
- 1
- 2
- 146
질문&답변
2024.01.11
lag, leag 강의에서 game-play-analysis-iv 문제
Soiejung 님, 안녕하세요. Soiejung님 버전 코드까지 같이 첨부해주셔서 제가 답변하기가 훨씬 수월해졌는데요 :) 위에 질문에 대한 답변은 이번주 일요일까지 드리겠습니다! 답변 바로 드리지 못한 점 양해부탁드립니다.
- 1
- 2
- 146