{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "활동 6a\n", "------------\n", "\n", "이번 활동의 목표는 지난 시간의 도구를 사용하여 BCNF 를 분해하고 그 과정을 이해 해보는 것이다. \n", "\n", "먼저, 도구와 샘플 데이터를 불러와야 한다. " ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from closure_v2 import compute_closure, display_side_by_side, print_setup # python2 인 경우\n", "from closure_v3 import compute_closure, display_side_by_side, print_setup # python3 인 경우" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Connected: @None'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%load_ext sql\n", "%sql sqlite://" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " * sqlite://\n", "Done.\n", "Done.\n", "1 rows affected.\n", "1 rows affected.\n", "1 rows affected.\n" ] }, { "data": { "text/plain": [ "[]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%sql DROP TABLE IF EXISTS T;\n", "CREATE TABLE T(course VARCHAR, classroom INT, time INT);\n", "INSERT INTO T VALUES ('CS 364', 132, 900);\n", "INSERT INTO T VALUES ('CS 245', 140, 1000);\n", "INSERT INTO T VALUES ('EE 101', 210, 900);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 문제 1\n", "\n", "먼저, `T`를 BCNF 형태로 분해해보자. `compute_closure` 함수를 사용하여 BCNF 알고리즘의 각 단계를 따라가보자. 그리고 테이블을 분해해 BCNF 정규화를 따르도록 새로운 테이블을 만들어 보자(새로운 SQL 테이블을 생성해야 한다):\n", "\n", "제공되는 도구에 `display_side_by_side`라는 함수를 쓰면 예쁜 표를 만들 수 있다!" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " * sqlite://\n", "Done.\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
courseclassroomtime
CS 364132900
CS 2451401000
EE 101210900
" ], "text/plain": [ "[('CS 364', 132, 900), ('CS 245', 140, 1000), ('EE 101', 210, 900)]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%sql SELECT * FROM T;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "다음과 같이 FD가 주어졌다." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Attributes = {time,course,classroom}\n", "FDs:\n", "\t=> \tcourse -> classroom\n", "\t=> \ttime,classroom -> course\n" ] } ], "source": [ "A = set(['course', 'classroom', 'time'])\n", "F = [('course', 'classroom'), (set(['classroom', 'time']), 'course')]\n", "print_setup(A, F)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q:** 이 FD 가 나타내는 현실 세계의 제약 조건은 무엇인가?\n", "\n", "이제, `compute_closure` 함수를 사용하여 BCNF 정규화를 따르도록 테이블을 분해해보자:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# X^+ != A 와 X^+ != X 를 만족하는 X를 찾아야 한다\n", "X = set( )\n", "compute_closure(X, F)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "테이블을 $T_1$과 $T_2$로 분해해보자:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%sql\n", "DROP TABLE IF EXISTS T1;\n", "CREATE TABLE T1 AS SELECT DISTINCT * FROM (\n", " # 작성해야 하는 SELECT-FROM 부분 \n", ");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%sql\n", "DROP TABLE IF EXISTS T2;\n", "CREATE TABLE T2 AS SELECT DISTINCT * FROM (\n", " # 작성해야 하는 SELECT-FROM 부분\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "아래와 같이 분해된 테이블을 출력 코드를 실행해보자:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "l = %sql SELECT * FROM T1;\n", "r = %sql SELECT * FROM T2;\n", "display_side_by_side(l,r)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q:** BCNF 정규화를 따르고 있는가?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 문제 2\n", "\n", "이 부분에서는 BCNF 정규화의 단점에 대해서 살펴보자. 간략하게 살펴 보자.\n", "\n", "기존의 FD가 여전히 유지되도록 $T_1$ 과/또는 $T_2$에 새로운 줄을 추가 할 수 있는지 확인해보자. 이 때, **추가되는 새로운 줄은 $T_1$과 $T_2$이 다시 한 테이블로 합쳐졌을 때 기존의 FD와 어긋나야 한다**. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%sql\n", "INSERT INTO T1 VALUES ( );\n", "INSERT INTO T2 VALUES ( );" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제, SQL 질의문을 사용하여 두 테이블을 합쳐서 원래의 모습으로 바꾸어보자:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%sql\n", "SELECT \n", "FROM \n", "WHERE ;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q:** 어디서 잘못되었는가?? 이런 문제를 방지하려면 어떻게 해야하는가?" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" } }, "nbformat": 4, "nbformat_minor": 2 }