Mysql 교묘 한 join 최적화 sql 방법 상세 설명
관련 건축 표 문 구 는 다음 과 같 습 니 다.https://github.com/YangBaohust/my_sql
user1 ,
+----+-----------+-----------------+---------------------------------+
| id | user_name | comment | mobile |
+----+-----------+-----------------+---------------------------------+
| 1 | | | 138245623,021-382349 |
| 2 | | | 159384292,022-483432,+86-392432 |
| 3 | | | 183208243,055-8234234 |
| 4 | | | 293842295,098-2383429 |
| 5 | NULL | | 993267899 |
+----+-----------+-----------------+---------------------------------+
user2 ,
+----+--------------+-----------+
| id | user_name | comment |
+----+--------------+-----------+
| 1 | | |
| 2 | | |
| 3 | | |
| 4 | | |
| 5 | NULL | |
+----+--------------+-----------+
user1_kills ,
+----+-----------+---------------------+-------+
| id | user_name | timestr | kills |
+----+-----------+---------------------+-------+
| 1 | | 2013-01-10 00:00:00 | 10 |
| 2 | | 2013-02-01 00:00:00 | 2 |
| 3 | | 2013-02-05 00:00:00 | 12 |
| 4 | | 2013-02-12 00:00:00 | 22 |
| 5 | | 2013-01-11 00:00:00 | 20 |
| 6 | | 2013-02-07 00:00:00 | 17 |
| 7 | | 2013-02-08 00:00:00 | 35 |
| 8 | | 2013-01-10 00:00:00 | 3 |
| 9 | | 2013-01-22 00:00:00 | 9 |
| 10 | | 2013-02-11 00:00:00 | 5 |
+----+-----------+---------------------+-------+
user1_equipment ,
+----+-----------+--------------+-----------------+-----------------+
| id | user_name | arms | clothing | shoe |
+----+-----------+--------------+-----------------+-----------------+
| 1 | | | | |
| 2 | | | | |
| 3 | | | | |
| 4 | | | | |
+----+-----------+--------------+-----------------+-----------------+
1.left join 을 사용 하여 자구 에 최적화 하지 않 음예:취 경 팀 에서 오 공 친구 권 에 속 하지 않 는 사람 을 찾 아 라.
+----+-----------+-----------------+-----------------------+
| id | user_name | comment | mobile |
+----+-----------+-----------------+-----------------------+
| 1 | | | 138245623,021-382349 |
| 3 | | | 183208243,055-8234234 |
| 4 | | | 293842295,098-2383429 |
+----+-----------+-----------------+-----------------------+
not in 서법:
select * from user1 a where a.user_name not in (select user_name from user2 where user_name is not null);
left join 쓰기:우선 username 연 결 된 외부 연결 데이터 세트
select a.*, b.* from user1 a left join user2 b on (a.user_name = b.user_name);
+----+-----------+-----------------+---------------------------------+------+-----------+-----------+
| id | user_name | comment | mobile | id | user_name | comment |
+----+-----------+-----------------+---------------------------------+------+-----------+-----------+
| 2 | | | 159384292,022-483432,+86-392432 | 1 | | |
| 1 | | | 138245623,021-382349 | NULL | NULL | NULL |
| 3 | | | 183208243,055-8234234 | NULL | NULL | NULL |
| 4 | | | 293842295,098-2383429 | NULL | NULL | NULL |
| 5 | NULL | | 993267899 | NULL | NULL | NULL |
+----+-----------+-----------------+---------------------------------+------+-----------+-----------+
a 표 의 모든 데 이 터 를 볼 수 있 습 니 다.b 표 의 데 이 터 는 b.user 밖 에 없습니다.name 과 a.username 이 같 아야 표시 되 고 나머지 는 null 값 으로 채 워 집 니 다.취 경 팀 에서 오 공 친구 권 에 속 하지 않 는 사람 을 찾 으 려 면 b.username 에 필터 조건 추가 b.username is null 이면 됩 니 다.
select a.* from user1 a left join user2 b on (a.user_name = b.user_name) where b.user_name is null;
+----+-----------+-----------------+-----------------------+
| id | user_name | comment | mobile |
+----+-----------+-----------------+-----------------------+
| 1 | | | 138245623,021-382349 |
| 3 | | | 183208243,055-8234234 |
| 4 | | | 293842295,098-2383429 |
| 5 | NULL | | 993267899 |
+----+-----------+-----------------+-----------------------+
여기 보 니 집중 적 으로 백 룡 마 가 하나 더 생 겼 습 니 다.여과 조건 a.user 을 계속 추가 하 세 요.name is not null 이면 됩 니 다.
select a.* from user1 a left join user2 b on (a.user_name = b.user_name) where b.user_name is null and a.user_name is not null;
2.left join 을 사용 하여 양자 조회 최적화예:취 경 팀 의 오 공 친구 들 의 닉네임 보기
+-----------+-----------------+-----------+
| user_name | comment | comment2 |
+-----------+-----------------+-----------+
| | | NULL |
| | | |
| | | NULL |
| | | NULL |
| NULL | | NULL |
+-----------+-----------------+-----------+
하위 검색 쓰기:
select a.user_name, a.comment, (select comment from user2 b where b.user_name = a.user_name) comment2 from user1 a;
left join 쓰기:
select a.user_name, a.comment, b.comment comment2 from user1 a left join user2 b on (a.user_name = b.user_name);
3.join 을 사용 하여 집합 서브 조회 최적화예:추출 팀 에서 모든 사람 이 몬스터 를 가장 많이 때 리 는 날 짜 를 조회 합 니 다.
+----+-----------+---------------------+-------+
| id | user_name | timestr | kills |
+----+-----------+---------------------+-------+
| 4 | | 2013-02-12 00:00:00 | 22 |
| 7 | | 2013-02-08 00:00:00 | 35 |
| 9 | | 2013-01-22 00:00:00 | 9 |
+----+-----------+---------------------+-------+
집합 서브 조회 쓰기:
select * from user1_kills a where a.kills = (select max(b.kills) from user1_kills b where b.user_name = a.user_name);
join 쓰기:먼저 두 표 가 연 결 된 결과 집 을 보고 지면 을 절약 하기 위해 저팔계 의 몬스터 데이터 만 추출 한 것 을 보면
select a.*, b.* from user1_kills a join user1_kills b on (a.user_name = b.user_name) order by 1;
+----+-----------+---------------------+-------+----+-----------+---------------------+-------+
| id | user_name | timestr | kills | id | user_name | timestr | kills |
+----+-----------+---------------------+-------+----+-----------+---------------------+-------+
| 5 | | 2013-01-11 00:00:00 | 20 | 5 | | 2013-01-11 00:00:00 | 20 |
| 5 | | 2013-01-11 00:00:00 | 20 | 6 | | 2013-02-07 00:00:00 | 17 |
| 5 | | 2013-01-11 00:00:00 | 20 | 7 | | 2013-02-08 00:00:00 | 35 |
| 6 | | 2013-02-07 00:00:00 | 17 | 7 | | 2013-02-08 00:00:00 | 35 |
| 6 | | 2013-02-07 00:00:00 | 17 | 5 | | 2013-01-11 00:00:00 | 20 |
| 6 | | 2013-02-07 00:00:00 | 17 | 6 | | 2013-02-07 00:00:00 | 17 |
| 7 | | 2013-02-08 00:00:00 | 35 | 5 | | 2013-01-11 00:00:00 | 20 |
| 7 | | 2013-02-08 00:00:00 | 35 | 6 | | 2013-02-07 00:00:00 | 17 |
| 7 | | 2013-02-08 00:00:00 | 35 | 7 | | 2013-02-08 00:00:00 | 35 |
+----+-----------+---------------------+-------+----+-----------+---------------------+-------+
두 표 가 user 를 통과 하 는 것 을 볼 수 있 습 니 다.name 자체 연결 을 진행 하려 면 a 표 의 모든 필드 에 group by 를 진행 하고 b 표 의 max(kills)를 가 져 오 십시오.a.kills=max(b.kills)만 있 으 면 요 구 를 만족 시 킬 수 있 습 니 다.sql 은 다음 과 같 습 니 다.
select a.* from user1_kills a join user1_kills b on (a.user_name = b.user_name) group by a.id, a.user_name, a.timestr, a.kills having a.kills = max(b.kills);
4.join 을 사용 하여 그룹 선택예:세 번 째 예 에 대해 업 그 레이 드 를 하고 추출 팀 에서 모든 사람 이 몬스터 를 가장 많이 때 리 는 앞의 두 날 짜 를 조회 합 니 다.
+----+-----------+---------------------+-------+
| id | user_name | timestr | kills |
+----+-----------+---------------------+-------+
| 3 | | 2013-02-05 00:00:00 | 12 |
| 4 | | 2013-02-12 00:00:00 | 22 |
| 5 | | 2013-01-11 00:00:00 | 20 |
| 7 | | 2013-02-08 00:00:00 | 35 |
| 9 | | 2013-01-22 00:00:00 | 9 |
| 10 | | 2013-02-11 00:00:00 | 5 |
+----+-----------+---------------------+-------+
Oacle 에서 분석 함 수 를 통 해 실현 할 수 있 습 니 다.
select b.* from (select a.*, row_number() over(partition by user_name order by kills desc) cnt from user1_kills a) b where b.cnt <= 2;
유 감 스 럽 지만 위의 sql 은 my sql 에서 ERROR 1064(42000)를 잘못 보 고 했 습 니 다.You have an error in your SQL syntax;my sql 은 분석 함 수 를 지원 하지 않 기 때 문 입 니 다.하지만 아래 의 방식 으로 이 루어 질 수 있다.먼저 두 표 에 대해 자체 관 계 를 하고 편폭 을 절약 하기 위해 손오공 의 데이터 만 꺼낸다.
select a.*, b.* from user1_kills a join user1_kills b on (a.user_name=b.user_name and a.kills<=b.kills) order by a.user_name, a.kills desc;
+----+-----------+---------------------+-------+----+-----------+---------------------+-------+
| id | user_name | timestr | kills | id | user_name | timestr | kills |
+----+-----------+---------------------+-------+----+-----------+---------------------+-------+
| 4 | | 2013-02-12 00:00:00 | 22 | 4 | | 2013-02-12 00:00:00 | 22 |
| 3 | | 2013-02-05 00:00:00 | 12 | 3 | | 2013-02-05 00:00:00 | 12 |
| 3 | | 2013-02-05 00:00:00 | 12 | 4 | | 2013-02-12 00:00:00 | 22 |
| 1 | | 2013-01-10 00:00:00 | 10 | 1 | | 2013-01-10 00:00:00 | 10 |
| 1 | | 2013-01-10 00:00:00 | 10 | 3 | | 2013-02-05 00:00:00 | 12 |
| 1 | | 2013-01-10 00:00:00 | 10 | 4 | | 2013-02-12 00:00:00 | 22 |
| 2 | | 2013-02-01 00:00:00 | 2 | 1 | | 2013-01-10 00:00:00 | 10 |
| 2 | | 2013-02-01 00:00:00 | 2 | 3 | | 2013-02-05 00:00:00 | 12 |
| 2 | | 2013-02-01 00:00:00 | 2 | 4 | | 2013-02-12 00:00:00 | 22 |
| 2 | | 2013-02-01 00:00:00 | 2 | 2 | | 2013-02-01 00:00:00 | 2 |
+----+-----------+---------------------+-------+----+-----------+---------------------+-------+
위의 표 에서 우 리 는 손오공 이 몬스터 를 때 리 기 전 두 명의 수량 이 22 와 12 라 는 것 을 알 고 있다.그러면 a 표 의 모든 필드 에 대해 group by 를 하고 b 표 의 id 에 대해 count 를 해 야 한다.count 값 이 2 보다 적 으 면 요 구 를 만족 시 킬 수 있다.sql 은 다음 과 같이 바 꾸 었 다.
select a.* from user1_kills a join user1_kills b on (a.user_name=b.user_name and a.kills<=b.kills) group by a.id, a.user_name, a.timestr, a.kills having count(b.id) <= 2;
5.피리 칼 적 연관 성 을 사용 하여 일렬 로 여러 줄 돌리 기예:팀 의 모든 전화 번 호 를 한 줄 로 바 꿉 니 다.
원본 데이터:
+-----------+---------------------------------+
| user_name | mobile |
+-----------+---------------------------------+
| | 138245623,021-382349 |
| | 159384292,022-483432,+86-392432 |
| | 183208243,055-8234234 |
| | 293842295,098-2383429 |
| NULL | 993267899 |
+-----------+---------------------------------+
원 하 는 데이터:
+-----------+-------------+
| user_name | mobile |
+-----------+-------------+
| | 138245623 |
| | 021-382349 |
| | 159384292 |
| | 022-483432 |
| | +86-392432 |
| | 183208243 |
| | 055-8234234 |
| | 293842295 |
| | 098-2383429 |
| NULL | 993267899 |
+-----------+-------------+
당승 에 게 전화 가 두 통 있 는 것 을 볼 수 있 기 때문에 그 는 두 줄 이 필요 하 다.우 리 는 먼저 모든 사람의 전화번호 수량 을 구 한 후에 서열 표 한 장과 피리 카드 축적 관 계 를 진행 할 수 있다.편폭 을 절약 하기 위해 당승 의 데이터 만 꺼 낼 수 있다.
select a.id, b.* from tb_sequence a cross join (select user_name, mobile, length(mobile)-length(replace(mobile, ',', ''))+1 size from user1) b order by 2,1;
+----+-----------+---------------------------------+------+
| id | user_name | mobile | size |
+----+-----------+---------------------------------+------+
| 1 | | 138245623,021-382349 | 2 |
| 2 | | 138245623,021-382349 | 2 |
| 3 | | 138245623,021-382349 | 2 |
| 4 | | 138245623,021-382349 | 2 |
| 5 | | 138245623,021-382349 | 2 |
| 6 | | 138245623,021-382349 | 2 |
| 7 | | 138245623,021-382349 | 2 |
| 8 | | 138245623,021-382349 | 2 |
| 9 | | 138245623,021-382349 | 2 |
| 10 | | 138245623,021-382349 | 2 |
+----+-----------+---------------------------------+------+
a.id 에 대응 하 는 것 은 바로 몇 번 째 전화번호 입 니 다.size 는 전체 전화번호 수량 이기 때문에 관련 조건(a.id<=b.size)을 추가 하여 위의 sql 을 계속 조정 할 수 있 습 니 다.
select b.user_name, replace(substring(substring_index(b.mobile, ',', a.id), char_length(substring_index(mobile, ',', a.id-1)) + 1), ',', '') as mobile from tb_sequence a cross join (select user_name, concat(mobile, ',') as mobile, length(mobile)-length(replace(mobile, ',', ''))+1 size from user1) b on (a.id <= b.size);
6.피리 칼 적 연관 성 을 사용 하여 다 중 열 전환 다 중 줄예:취 경 조 의 모든 장 비 를 한 줄 로 변환 합 니 다.
원본 데이터:
+----+-----------+--------------+-----------------+-----------------+
| id | user_name | arms | clothing | shoe |
+----+-----------+--------------+-----------------+-----------------+
| 1 | | | | |
| 2 | | | | |
| 3 | | | | |
| 4 | | | | |
+----+-----------+--------------+-----------------+-----------------+
원 하 는 데이터:
+-----------+-----------+-----------------+
| user_name | equipment | equip_mame |
+-----------+-----------+-----------------+
| | arms | |
| | clothing | |
| | shoe | |
| | arms | |
| | clothing | |
| | shoe | |
| | arms | |
| | clothing | |
| | shoe | |
| | arms | |
| | clothing | |
| | shoe | |
+-----------+-----------+-----------------+
union 의 표기 법:
select user_name, 'arms' as equipment, arms equip_mame from user1_equipment
union all
select user_name, 'clothing' as equipment, clothing equip_mame from user1_equipment
union all
select user_name, 'shoe' as equipment, shoe equip_mame from user1_equipment
order by 1, 2;
join 의 쓰기:우선 피리 칼 데이터 세트 의 효 과 를 보면 당승 을 예 로 들 면
select a.*, b.* from user1_equipment a cross join tb_sequence b where b.id <= 3;
+----+-----------+--------------+-----------------+-----------------+----+
| id | user_name | arms | clothing | shoe | id |
+----+-----------+--------------+-----------------+-----------------+----+
| 1 | | | | | 1 |
| 1 | | | | | 2 |
| 1 | | | | | 3 |
+----+-----------+--------------+-----------------+-----------------+----+
케이스 를 사용 하여 위의 결 과 를 처리 합 니 다.
select user_name,
case when b.id = 1 then 'arms'
when b.id = 2 then 'clothing'
when b.id = 3 then 'shoe' end as equipment,
case when b.id = 1 then arms end arms,
case when b.id = 2 then clothing end clothing,
case when b.id = 3 then shoe end shoe
from user1_equipment a cross join tb_sequence b where b.id <=3;
+-----------+-----------+--------------+-----------------+-----------------+
| user_name | equipment | arms | clothing | shoe |
+-----------+-----------+--------------+-----------------+-----------------+
| | arms | | NULL | NULL |
| | clothing | NULL | | NULL |
| | shoe | NULL | NULL | |
+-----------+-----------+--------------+-----------------+-----------------+
coalesce 함 수 를 사용 하여 다 열 데 이 터 를 통합 합 니 다.
select user_name,
case when b.id = 1 then 'arms'
when b.id = 2 then 'clothing'
when b.id = 3 then 'shoe' end as equipment,
coalesce(case when b.id = 1 then arms end,
case when b.id = 2 then clothing end,
case when b.id = 3 then shoe end) equip_mame
from user1_equipment a cross join tb_sequence b where b.id <=3 order by 1, 2;
7.join 을 사용 하여 필터 조건 에 자신 을 포함 하 는 표를 업데이트 합 니 다.예:취 경 팀 과 오 공 친구 권 에 동시에 존재 하 는 사람 을 취 경 팀 에서 comment 필드 를'이 사람 이 오 공의 친구 권 에 있다'로 업데이트 한다.
우 리 는 자 연 스 럽 게 user 1 과 user 2 중 user 를 먼저 찾 고 싶 습 니 다.name 이 존재 하 는 사람,그리고 user 1 표를 업데이트 합 니 다.sql 은 다음 과 같 습 니 다.
update user1 set comment = ' ' where user_name in (select a.user_name from user1 a join user2 b on (a.user_name = b.user_name));
유 감 스 럽 지만 위의 sql 은 my sql 에서 오 류 를 보 고 했 습 니 다.ERROR 1093(HY 000):You can't specify target table'user 1'for update in FROM clause,목표 표 가 from 자구 에 있 는 표를 업데이트 할 수 없 음 을 알려 줍 니 다.그럼 다른 방법 은 없 을까요?우 리 는 in 의 쓰기 방법 을 join 의 방식 으로 바 꿀 수 있다.
select c.*, d.* from user1 c join (select a.user_name from user1 a join user2 b on (a.user_name = b.user_name)) d on (c.user_name = d.user_name);
+----+-----------+--------------+---------------------------------+-----------+
| id | user_name | comment | mobile | user_name |
+----+-----------+--------------+---------------------------------+-----------+
| 2 | | | 159384292,022-483432,+86-392432 | |
+----+-----------+--------------+---------------------------------+-----------+
그리고 join 이후 의 보 기 를 업데이트 하면 됩 니 다.
update user1 c join (select a.user_name from user1 a join user2 b on (a.user_name = b.user_name)) d on (c.user_name = d.user_name) set c.comment = ' ';
user 1 을 다시 보면 user 1 이 수정 되 었 음 을 볼 수 있 습 니 다.
select * from user1;
+----+-----------+-----------------------------+---------------------------------+
| id | user_name | comment | mobile |
+----+-----------+-----------------------------+---------------------------------+
| 1 | | | 138245623,021-382349 |
| 2 | | | 159384292,022-483432,+86-392432 |
| 3 | | | 183208243,055-8234234 |
| 4 | | | 293842295,098-2383429 |
| 5 | NULL | | 993267899 |
+----+-----------+-----------------------------+---------------------------------+
8.join 으로 중복 데이터 삭제우선 user 2 표 에 두 개의 데 이 터 를 삽입 합 니 다.
insert into user2(user_name, comment) values (' ', ' ');
insert into user2(user_name, comment) values (' ', ' ');
예:user 2 표 의 중복 데 이 터 를 삭제 하고 id 번호 가 큰 것 만 유지 합 니 다.
+----+--------------+-----------+
| id | user_name | comment |
+----+--------------+-----------+
| 1 | | |
| 2 | | |
| 3 | | |
| 4 | | |
| 5 | NULL | |
| 6 | | |
| 7 | | |
+----+--------------+-----------+
우선 중복 기록 보기
select a.*, b.* from user2 a join (select user_name, comment, max(id) id from user2 group by user_name, comment having count(*) > 1) b on (a.user_name=b.user_name and a.comment=b.comment) order by 2;
+----+-----------+-----------+-----------+-----------+------+
| id | user_name | comment | user_name | comment | id |
+----+-----------+-----------+-----------+-----------+------+
| 1 | | | | | 6 |
| 6 | | | | | 6 |
| 2 | | | | | 7 |
| 7 | | | | | 7 |
+----+-----------+-----------+-----------+-----------+------+
이 어(a.id
delete a from user2 a join (select user_name, comment, max(id) id from user2 group by user_name, comment having count(*) > 1) b on (a.user_name=b.user_name and a.comment=b.comment) where a.id < b.id;
user 2 를 보면 중복 데이터 가 삭제 되 었 음 을 볼 수 있 습 니 다.
select * from user2;
+----+--------------+-----------+
| id | user_name | comment |
+----+--------------+-----------+
| 3 | | |
| 4 | | |
| 5 | NULL | |
| 6 | | |
| 7 | | |
+----+--------------+-----------+
요약:여기까지 소개 하 겠 습 니 다.여러분 이 관심 이 있 으 면 데 이 터 를 많이 만 든 다음 에 서로 다른 sql 쓰기 가 실행 시간 에서 의 차 이 를 비교 할 수 있 습 니 다.본 논문 의 예 는 모 과 망 에서 따 온 것 이다.
자,이상 이 이 글 의 모든 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
MySQL에서 JSON 인덱싱 - aarondfrancis사람들은 종종 MySQL로 JSON을 인덱싱할 수 없다고 말하지만 완전히 정확하지는 않습니다. MySQL로 JSON 열을 인덱싱하는 것은 완전히 가능합니다! 사람들은 종종 MySQL로 JSON을 인덱싱할 수 없다고 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.