JavaRush /Java Blog /Random-KO /우리는 데이터베이스와 SQL 언어를 분석합니다. (5부 - 연결 및 조인) - "A부터 Z까지 Java...
Roman Beekeeper
레벨 35

우리는 데이터베이스와 SQL 언어를 분석합니다. (5부 - 연결 및 조인) - "A부터 Z까지 Java 프로젝트"

Random-KO 그룹에 게시되었습니다
Java 프로젝트 생성에 관한 시리즈 기사입니다(다른 자료에 대한 링크는 끝에 있습니다). 그 목표는 핵심 기술을 분석하는 것이고, 그 결과는 텔레그램 봇을 작성하는 것입니다. 안녕하세요, 소프트웨어의 미래 선배이자 선배 여러분. 이전 부분( 숙제 확인 ) 에서 말했듯이 오늘은 새로운 자료가 있을 것입니다. 특히 열정이 있는 분들을 위해 이미 모든 것을 알고 있는 분들과, 모르지만 구글링을 하고 싶은 분들이 연습하고 실력을 테스트할 수 있도록 흥미로운 숙제를 파헤쳐봤습니다. "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결 및 조인 - 1오늘은 연결 및 조인 유형에 대해 이야기하겠습니다.

데이터베이스의 관계 유형

"A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결 및 조인 - 2관계가 무엇인지 이해하려면 외래 키가 무엇인지 기억해야 합니다. 잊으신 분들을 위해 시리즈의 시작을 환영합니다 .

일대다

국가와 도시에 대한 예를 기억해 봅시다. 도시에는 국가가 있어야 한다는 것은 분명합니다. 국가와 도시를 어떻게 연결하나요? 각 도시에는 해당 도시가 속한 국가의 고유 식별자(ID)를 첨부해야 합니다. 이미 이 작업을 수행했습니다. 이것을 연결 유형 중 하나인 일대다(일대다) 라고 합니다 (영어 버전인 일대다를 아는 ​​것도 좋을 것입니다). 바꿔 말하면 여러 도시가 한 국가에 속할 수 있습니다. 일대다 관계라는 것을 기억해야 합니다. 지금까지는 분명했습니다. 그렇죠? 그렇지 않다면 다음 "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결 및 조인 - 3은 인터넷의 첫 번째 사진입니다. 고객과 고객의 주문이 있음을 보여줍니다. 한 고객이 두 개 이상의 주문을 받을 수 있다는 것은 의미가 있습니다. 일대다 방식이 있습니다 :) 또는 또 다른 예: "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결과 조인 - 4출판사, 저자, 서적이라는 세 개의 테이블이 있습니다. 파산하기 싫고 성공하고 싶은 출판사마다 저자가 한 명 이상 있습니다. 동의하지 않나요? 차례로 각 저자는 두 권 이상의 책을 가질 수 있습니다. 이에 대해서도 의심의 여지가 없습니다. 그리고 이것은 다시 한 명의 저자가 많은 책과 연결되고, 한 출판사가 많은 저자와 연결되는 것을 의미합니다 . 더 많은 예를 들 수 있습니다. 처음에는 인식의 어려움은 추상적으로 생각하는 법, 즉 외부에서 테이블과 상호 작용을 보는 법을 배우는 데에만 있을 수 있습니다.

일대일 (일대일)

이는 일대다 통신의 특수한 경우라고 할 수 있다. 한 테이블의 하나의 레코드가 다른 테이블의 하나의 레코드에만 관련되는 상황입니다. 삶에서 어떤 예가 있을 수 있습니까? 일부다처제를 제외한다면, 남편과 아내 사이에는 일대일 관계가 있다고 말할 수 있습니다. 일부다처제가 허용된다고 하더라도 각 아내는 여전히 한 명의 남편만 가질 수 있습니다. 부모에 대해서도 마찬가지입니다. 각 사람은 오직 한 명의 생물학적 아버지와 한 명의 생물학적 어머니만을 가질 수 있습니다. 명시적인 일대일 관계. 이 글을 쓰는 동안 다음과 같은 생각이 들었습니다. 이미 일대일 관계가 있는 경우 일대일 관계를 다른 테이블의 두 레코드로 나누는 이유는 무엇일까요? 나는 스스로 답을 생각해 냈습니다. 이러한 기록은 다른 방식으로 다른 기록과 연결될 수도 있습니다. 내가 무슨 말을하는거야? 일대일 연결의 또 다른 예는 국가와 대통령 간의 관계입니다. "국가" 테이블에 대통령에 대한 모든 데이터를 기록하는 것이 가능합니까? 예, 가능합니다. SQL은 아무 말도 하지 않습니다. 그런데 대통령도 사람이라고 생각하면... 그리고 그 사람도 아내(또 다른 일대일 관계)와 자녀(또 다른 일대다 관계)를 가질 수도 있고 그러면 그럴 것이라는 것이 밝혀진다. 대통령 부인, 자녀들과 나라를 연결하는 데 필요한… 미친 것 같죠? :D 이 연결에 대한 다른 많은 예가 있을 수 있습니다. 또한 이러한 상황에서는 일대다 관계와 달리 두 테이블 모두에 외래 키를 추가할 수 있습니다.

다대다

이미 이름을 보면 우리가 무엇에 대해 이야기할지 짐작할 수 있습니다. 종종 인생에서, 그리고 우리의 삶을 프로그래밍할 때, 위의 유형의 연결이 우리에게 필요한 것을 설명하기에 충분하지 않은 상황이 있습니다. 우리는 이미 출판사, 책, 작가에 대해 이야기했습니다. 여기에는 너무 많은 연결이 있습니다... 각 출판물에는 여러 명의 작성자가 있을 수 있습니다(일대다 연결). 동시에 각 저자는 여러 출판사를 가질 수 있습니다 (예를 들어 작가가 한 곳에서 출판되었거나 돈 문제로 다투거나 다른 출판사로 갔을 때). 그리고 이것은 다시 일대다 관계입니다. 또는 각 저자는 여러 권의 책을 가질 수 있지만 각 책에는 여러 명의 저자가 있을 수도 있습니다. 다시 말하지만, 저자와 책, 책과 저자 사이의 일대다 관계입니다. 이 예에서 우리는 보다 공식적인 결론을 도출할 수 있습니다.

두 개의 테이블 A와 B가 있다고 가정해 보겠습니다.

A는 B와 일대다 관계를 가질 수 있습니다.

그러나 B는 하나가 다수와 관련되듯이 A와도 관련될 수 있습니다.

이는 다대다 관계가 있음을 의미합니다.

SQL에서 이전 연결 유형을 설정하는 방법은 명확했습니다. 해당 레코드의 ID를 많은 레코드에 전달하기만 하면 됩니다. 그렇죠? 한 국가는 여러 도시에 해당 ID를 외래 키로 제공합니다. 다대다 관계는 어떻게 해야 할까요 ? 이 방법은 적합하지 않습니다. 두 테이블을 연결하는 다른 테이블을 추가해야 합니다. 예를 들어, MySQL로 가서 새로운 데이터베이스 Manytomany를 생성하고 이름과 ID만 포함하는 작성자와 책이라는 두 개의 테이블을 생성해 보겠습니다. CREATE DATABASE Manytomany; 많은 것을 사용하십시오; CREATE TABLE 작성자( id INT AUTO_INCREMENT, 이름 VARCHAR(100), PRIMARY KEY (id) ); CREATE TABLE 책( id INT AUTO_INCREMENT, 이름 VARCHAR(100), PRIMARY KEY (id) ); "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결 및 조인 - 5이제 작성자 테이블과 도서 테이블의 두 개의 외래 키를 갖는 세 번째 테이블을 생성해 보겠습니다. 이 링크는 고유합니다. 즉, 동일한 키를 가진 레코드를 두 번 추가하는 것은 불가능합니다: CREATE TABLE Authors_x_books ( book_id INT NOT NULL,author_id INT NOT NULL, FOREIGN KEY (book_id) REFERENCES book(id), FOREIGN KEY (author_id) REFERENCES 작성자 (id ), UNIQUE (book_id, 저자_id) ); "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결과 조인 - 6여기서는 별도로 설명이 필요한 몇 가지 새로운 기능을 사용했습니다.
  • NOT NULL은 필드가 항상 채워져야 함을 의미하며, 그렇지 않으면 SQL이 그렇게 알려줍니다.
  • UNIQUE는 하나의 필드 또는 여러 필드가 테이블에서 고유해야 함을 의미합니다. 고유 식별자 외에도 각 레코드에 대해 하나 이상의 필드가 고유해야 하는 경우가 종종 있습니다. 그리고 UNIQUE는 바로 이 문제에 대한 책임이 있습니다.
내 경험에 따르면, 이전 시스템에서 새 시스템으로 이동할 때 개발자로서 우리는 이전 시스템의 ID를 저장하여 작업하고 자체 시스템을 만들어야 합니다. 왜 자신만의 것을 만들고 오래된 것을 사용하지 않습니까? 충분히 고유하지 않을 수도 있고, ID 생성에 대한 이러한 접근 방식이 더 이상 관련성이 없고 제한적일 수도 있습니다. 이를 위해 이전 ID 이름도 테이블에서 고유하게 만들었습니다. 이를 확인하려면 데이터를 추가해야 합니다. 책 및 저자 추가: NSERT INTO book (name) VALUES ("book1"); INSERT INTO 작성자(이름) VALUES("author1"); 이전 기사에서 ID가 1과 1이라는 것을 이미 알고 있습니다. 따라서 세 번째 테이블에 즉시 레코드를 추가할 수 있습니다. INSERT INTOauthors_x_books VALUES (1,1); 그리고 마지막 명령을 다시 반복하기 전까지는 모든 것이 잘 될 것입니다. 즉, 동일한 ID를 다시 적어 두십시오. "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결과 조인 - 7결과는 자연스러울 것입니다. 즉, 오류입니다. 중복이 있을 겁니다. 항목이 기록되지 않습니다. 이것이 바로 다대다 연결이 생성되는 방법입니다... 이 모든 것이 매우 멋지고 흥미롭지만 논리적인 질문이 생깁니다. 이 정보를 어떻게 얻을 수 있을까요? 서로 다른 테이블의 데이터를 결합하여 하나의 답을 얻는 방법은 무엇입니까? 이에 대해서는 다음 부분에서 이야기하겠습니다.))

연결(조인)

전편에서는 조인이 무엇인지, 어디에 사용하는지 바로 이해할 수 있도록 준비했습니다. 이해가 되자마자 모든 것이 즉시 매우 단순해지고, 조인에 관한 모든 기사가 아기의 눈처럼 명확해질 것이라고 깊이 확신하기 때문입니다. D 대략적으로 그리고 일반적으로 조인은 여러 테이블을 통해 결과를 얻는 것입니다. JOIN(영어 조인에서 조인). 그게 전부입니다...) 그리고 조인하려면 테이블을 조인할 필드를 지정해야 합니다. 악마는 그림만큼 무섭지 않죠?) 다음으로 조인에는 어떤 종류가 있고 어떻게 사용하는지에 대해서만 이야기해보겠습니다. 조인에는 다양한 유형이 있으므로 모두 고려하지는 않습니다. 우리에게 정말로 필요한 것만. 그렇기 때문에 우리는 Cross나 Natural과 같은 이국적인 조인에 관심이 없습니다. 한 가지 더 뉘앙스를 기억해야 한다는 사실을 완전히 잊었습니다. 테이블과 필드에는 별칭 (가명)이 있을 수 있습니다. 조인에 편리하게 사용됩니다. 예를 들어 다음과 같이 할 수 있습니다: SELECT * FROM table1; 쿼리에서 table1을 자주 사용하는 경우 별칭을 지정할 수 있습니다. SELECT* FROM table1 as t1; 또는 더 쉽게 작성할 수 있습니다: SELECT * FROM table1 t1; 그런 다음 나중에 쿼리에서 t1을 이 테이블의 별칭으로 사용할 수 있습니다 .

내부 조인

가장 일반적이고 간단한 조인입니다. 두 개의 테이블과 이를 조인할 수 있는 필드가 있으면 두 테이블에 관계가 있는 모든 레코드가 선택된다는 의미입니다. 왠지 말하기 어려웠습니다. 예를 살펴보겠습니다. 도시 데이터베이스에 하나의 레코드를 추가해 보겠습니다. 도시에 대한 항목 하나와 국가에 대한 항목 하나: $ INSERT INTO country VALUES(5, "Uzbekistan", 34036800); $ INSERT INTO 도시(이름, 인구) VALUES("트빌리시", 1171100); 테이블에 도시가 없는 국가와 테이블에 국가와 연결되지 않은 도시를 추가했습니다. 따라서 INNER JOIN은 두 테이블에 있는 연결에 대한 모든 레코드를 발행하는 데 관여합니다. table1과 table2 두 테이블을 조인할 때의 일반적인 구문은 다음과 같습니다. SELECT * FROM table1 t1 INNER JOIN table2 ON t1.id = t2.t1_id; 그러면 두 테이블에 관계가 있는 모든 레코드가 반환됩니다. 우리의 경우 도시와 함께 국가에 대한 정보를 받으려면 다음과 같이 나타납니다. $ SELECT * FROM city ci INNER JOIN country co ON ci.country_id = co.id; "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결과 조인 - 8여기에서는 이름은 동일하지만 도시 필드가 먼저 오고 국가 필드가 그 다음이라는 것을 확실히 알 수 있습니다. 하지만 위에서 추가한 두 항목은 거기에 없습니다. 이것이 바로 INNER JOIN이 작동하는 방식이기 때문입니다.

왼쪽 조인

인접한 테이블에 해당 레코드가 없다는 사실로 인해 기본 테이블의 필드 손실이 만족스럽지 않은 경우가 매우 자주 있습니다. 이것이 바로 LEFT JOIN의 목적입니다. 이전 요청에서 INNER 대신 LEFT를 지정한 경우 응답에 다른 도시를 추가합니다. Tbilisi: $ SELECT * FROM city ci LEFT JOIN country co ON ci.country_id = co.id; "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결과 조인 - 9트빌리시에 관한 새로운 항목이 있으며 해당 국가와 관련된 모든 항목은 null 입니다 . 이렇게 사용되는 경우가 많습니다.

바로 가입

여기서는 모든 필드가 연결의 왼쪽이 아닌 오른쪽에서 선택된다는 점에서 LEFT JOIN과 차이가 있습니다. 즉, 도시가 아닌 모든 국가가 선택됩니다. $ SELECT * FROM city ci RIGHT JOIN country co ON ci.country_id = co.id; "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결 및 조인 - 10이제 이 경우 트빌리시는 없을 것이 분명하지만 우즈베키스탄을 갖게 될 것입니다. 그런 것…))

조인 보안

이제 저는 후배들이 조인의 본질을 이해하고 있음을 확신시키기 위해 인터뷰 전에 벼락치기하는 전형적인 그림을 보여주고 싶습니다. "A부터 Z까지의 Java 프로젝트": 데이터베이스와 SQL 언어를 분석합니다.  5부 - 연결 및 조인 - 11여기에서는 모든 것이 세트 형태로 표시되고 각 원은 테이블입니다. 그리고 칠해진 부분이 SELECT에 표시되는 부분입니다. 한번 보자:
  • INNER JOIN은 집합의 교차점, 즉 A와 B라는 두 테이블에 연결된 레코드일 뿐입니다.
  • LEFT JOIN은 A와 교차(연결)되는 테이블 B의 모든 레코드를 포함하여 테이블 A의 모든 레코드입니다.
  • RIGHT JOIN은 LEFT JOIN과 정확히 반대입니다. 즉, 테이블 B의 모든 레코드와 관계가 있는 A의 레코드입니다.
결국 이 그림은 선명해야 합니다.))

숙제

이번에는 작업이 매우 흥미로울 것이며 문제를 성공적으로 해결한 모든 사람들은 SQL 측 작업을 시작할 준비가 되었음을 확신할 수 있습니다! 과제는 씹히지 않고 중학생을 대상으로 작성되었기 때문에 쉽거나 지루하지 않을 거예요 :) 과제는 일주일 동안 직접 해보고, 자세한 분석이 포함된 별도의 글을 게시하겠습니다. 내가 너에게 준 과제에 대한 해결책을.

실제 작업:

  1. id(기본 키), 이름, last_name, e_mail(고유) 필드가 포함된 'Student' 테이블을 생성하는 SQL 스크립트를 작성하세요.
  2. id, title(id + title = 기본 키) 필드가 포함된 'Book' 테이블을 생성하는 SQL 스크립트를 작성하세요. '학생'과 '도서'를 '학생' 일대다 '도서' 관계로 연결합니다.
  3. id(기본 키), 이름, last_name, e_mail(고유), 제목 필드가 포함된 'Teacher' 테이블을 생성하는 SQL 스크립트를 작성하세요.
  4. '학생'과 '교사'를 '학생' 다대다 교사 관계로 연결합니다.
  5. 성에 'oro'가 있는 '학생'을 선택하세요(예: 'Sid oro v', 'V oro novsky').
  6. 'Student' 테이블에서 모든 성('last_name')과 반복 횟수를 선택합니다. 데이터베이스에 이름이 같은 것이 있다는 것을 고려하십시오. 수량별로 내림차순으로 정렬합니다. 다음과 같아야 합니다.
    수량
    페트로프 15
    이바노프 12
    시도로프
  7. '학생'에서 가장 많이 반복되는 이름 상위 3개를 선택하세요. 수량별로 내림차순으로 정렬합니다. 다음과 같아야 합니다.
    이름 수량
    알렉산더 27
    세르게이 10
    베드로 7
  8. '도서'와 연계된 '교사' 수가 가장 많은 '학생'을 선택하고, 수량에 따라 내림차순으로 정렬합니다. 다음과 같아야 합니다.
    선생님의 성 학생의 성 도서 수량
    페트로프 시도로프 7
    이바노프 스미스 5
    페트로프 칸카바 2>
  9. 모든 '학생' 중에서 '도서'를 가장 많이 보유한 '선생님'을 선택하세요. 수량별로 내림차순으로 정렬합니다. 다음과 같아야 합니다.
    선생님의 성 도서 수량
    페트로프 9
    이바노프 5
  10. 모든 '학생'에 대한 '도서' 수가 7에서 11 사이인 '교사'를 선택하세요. 수량별로 내림차순으로 정렬합니다. 다음과 같아야 합니다.
    선생님의 성 도서 수량
    페트로프 열하나
    시도로프 9
    이바노프 7
  11. 'type' 필드(학생 또는 교사)와 함께 모든 'Teacher' 및 'Student'의 모든 'last_name' 및 'name'을 인쇄합니다. 'last_name'을 기준으로 알파벳순으로 정렬합니다. 다음과 같아야 합니다.
    유형
    이바노프 학생
    칸카바 선생님
    스미스 학생
    시도로프 선생님
    페트로프 선생님
  12. 기존 'Student' 테이블에 'rate' 열을 추가합니다. 여기에는 학생이 현재 수강 중인 강좌(1~6의 숫자 값)가 저장됩니다.
  13. 이 항목은 필수는 아니지만 플러스가 될 것입니다. 모든 '책'을 살펴보고 모든 '제목'을 쉼표로 구분하여 출력하는 함수를 작성하세요.

결론

데이터베이스에 관한 시리즈가 조금 끌렸습니다. 동의하다. 그러나 우리는 먼 길을 왔으며 그 결과 문제에 대한 지식을 갖게 되었습니다! 읽어주셔서 감사합니다. 프로젝트를 계속 진행하고 싶은 모든 사람은 GitHub 에서 계정을 만들고 내 계정을 구독해야 한다는 점을 상기시켜 드립니다 . :) 앞으로 더 많은 내용이 추가될 예정입니다. Maven과 Docker에 대해 이야기해 보겠습니다. 읽어주신 모든 분들께 감사드립니다. 다시 한 번 반복합니다. 걷는 사람이 길을 마스터할 것입니다 ;)

시리즈의 모든 자료 목록은 이 기사의 시작 부분에 있습니다.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION