안녕하세요. 지난번 질문드린이후 SQL관련 기초책을 찾아 열심히 공부를 하고 있습니다.
공부를 하는도중 다음과 같은 값을 구하려고 하는데 DISTINCT를 사용하면 쉽게 구할 수 있다고
온라인에서 찾은 예제를 보니 DISTINCT가 실행되는 과정에서 GROUP BY를 한 결과를 토대로 보여준다고 해서
GROUP BY로 여러 시도를 해 보았지만 결과가 정확하게 나오지 않아 좋은 방법이 있을까 하여 질문을 드립니다.
대상 테이블
|--------------------------------------------------| | id | user_id | access_ip | |--------------------------------------------------| | 1 | test | 1.2.3.4 | |--------------------------------------------------| | 2 | test | 1.2.1.1 | |--------------------------------------------------| | 3 | have | 1.2.3.4 | |--------------------------------------------------| | 4 | test | 1.2.1.1 | |--------------------------------------------------| | 5 | have | 1.2.3.4 | |--------------------------------------------------| | 6 | abcd | 1.2.3.4 | |--------------------------------------------------|
시도한 쿼리
SELECT * FROM `tables` WHERE (user_id) IN ( SELECT user_id FROM `tables` GROUP BY access_ip ) GROUP BY user_id ...
하는 도중 GROUP_CONCAT도 시도해 보고 있고, 마농님이 알려주신 BY PARTITION_BY
도 활용해서 해보고 있지만 쉽지 않네요.
목표
|----------------------------------------------------------------| | id | access_ip | group_member | |----------------------------------------------------------------| | 1 | 1.2.3.4 | test,have,abcd | |----------------------------------------------------------------| | 2 | 1.2.1.1 | test | |----------------------------------------------------------------|
자주 쓰일법한 쿼리문같아 많이 검색을 해봤는데 딱히 참고가 안되는 결과들만 나와 이렇게 부탁아닌 질문을 드립니다.
고견부탁드립니다.
----------------------------------------------------------------------------------------------------------------------------------
SELECT ip.access_ip, GROUP_CONCAT(DISTINCT id.user_id ORDER BY id.user_id ASC) AS user_list FROM user_accesslogs AS ip JOIN user_accesslogs AS id ON ip.access_ip = id.access_ip GROUP BY ip.access_ip;
책을보고 천천히 해보다 보니 다음과 같은 쿼리로 원하는 결과가 나온것 같습니다.
질문 주제와는 좀 동떨어졌지만요.. ㅜ
이렇게 구하는것이 맞는지.. 그리고 혹시 이것보다 더 나은 방법으로 쿼리하는방법이 있는지 궁금합니다.
더불어 user_list 에 출력되는 유저의 수를 구하려고 다음과 같이 추가로 쿼리를 만들었는데 더 좋게 수정할 수 있는 방법이 있을까요?
SELECT ip.access_ip, GROUP_CONCAT(DISTINCT id.user_id ORDER BY id.user_id ASC) AS user_list, COUNT(DISTINCT id.user_id) AS count FROM user_accesslogs AS ip JOIN user_accesslogs AS id ON ip.access_ip = id.access_ip GROUP BY ip.access_ip;
고견 부탁드립니다..
감사합니다. 정말 JOIN을 빼도 동일한 값이 나오네요.
제가 쿼리 작성시 생각한 바로는
1. 아이피를 그룹화(유일값) 한다.
2. 아이피에 속해있는 유저도 그룹화(유일값) 한다.
3. 두 값을 하나의 행에 정렬한다
개념으로 생각을 해서 조인을 각각해 별도로 구했습니다.
저것 조인하는것을 셀프조인이라고 부르던데 혹시 셀프조인은 어떤경우에 사용해야하는지 가능하시다면
예를 좀 들어주실 수 있으신가요?
저기 답변주신 내용에 덧붙혀 현재 유저가 존재하는지 여부도 필요하고 block_ip 컬럼에 null 인경우
block 상태가 아닌것으로 판단하게 하는 기능이 필요해 제가 추가로 작성한 쿼리는 다음과 같습니다.
SELECT lg.access_ip, black.block_ip , GROUP_CONCAT(DISTINCT CONCAT(lg.user_id,'|',usr.nickname) ORDER BY lg.user_id ASC) AS user_list, COUNT(DISTINCT lg.user_id) user_cnt , COUNT(DISTINCT lg.user_id) user_cnt FROM user_accesslogs AS lg JOIN users AS usr ON lg.user_id = usr.user_id LEFT JOIN ipblocks AS black ON black.block_ip = lg.access_ip GROUP BY lg.access_ip ORDER BY user_cnt DESC;
이 코드에서도 혹시 무언가 놓치고있는 부분이 있을까요?
고견을 부탁드립니다.
그룹바이 기본 개념에 위배되는 쿼리입니다.
MySQL 에서는 에러가 안나지만, 원래는 에러나는 쿼리입니다.
GROUP BY 기준항목이 아닌 일반항목은 집계함수와 함께 사용되어야 합니다.
집계함수 없이 바로 black.block_ip 가 사용되었네요. <- MySQL 에서만 에러 안남.
최종 쿼리엔 없지만 질문의 목표 결과에 id 가 포함된 부분도 같은 맥락으로 잘못된 부분입니다.
lg.access_ip 와 black.block_ip 가 1:1 관계라면?
GROUP BY 에 black.block_ip 를 추가하면 됩니다. -> GROUP BY lg.access_ip, black.block_ip
lg.access_ip 와 black.block_ip 가 1:m 관계라면?
어떤 기준을 세워서 어떤 방식으로 풀어야 할지 고민이 필요합니다.
안녕하세요 마농님.
지난번 알려주신 쿼리덕에 그날 업무이후 서점에 들러 SQL 기본서를 구매해서 공부했습니다.
계기에 용기를 불어넣어주셔서 감사합니다.
말씀대로 지금 사용하는 DBMS는 MYSQL입니다. 말씀데로 GROUP BY 관련 오류가 나지 않아서
문제해결은 했으나, 전혀 몰랐던 내용에다가 제가 읽었던 책에는 있지 않았던 내용인것 같아,
알려주신 지식을 이해하고자 마농님 댓글을 다시 읽어봐도 아직 제 지식이 부족해
이해가 잘 가지 않습니다. 공부를 더 해야할 것 같습니다.
말씀주신 쿼리대로 오늘 연습을 해 보고 새로운 지식을 쌓을 수 있도록 해보겠습니다.
업무에 바쁘실텐데 매번 관심 가져주셔서 너무 감사합니다.
좋은 하루되세요.