petch 함수
레코드를 배열 형식으로 저장
실습
# 인프리터와 상호작용하는 기능 import sys # GUI 애플리케이션을 만들기 위해 필요한 위젯 제공 from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout, QHBoxLayout, QComboBox, QTableWidget, QTableWidgetItem, QPushButton, QGroupBox, QTextEdit # MySQL 데이터베이스에 연결하고 쿼리를 실행하기 위한 도구 제공 import mysql.connector # 데이터 분석을 위한 데이터 구조와 도구 제공 # SQL 쿼리의 결과를 데이터프로엠으로 변환하여 쉽게 조작, 표시 import pandas as pd # 데이터베이스에 연결해서 쿼리를 실행하고 결과를 가져옴. def get_data_from_database(query): # MySQL 데이터베이스에 연결합니다. conn = mysql.connector.connect( host='127.0.0.1', user='root', password='0000', database='market_db' ) # 데이터베이스와 상호작용할 수 있는 커서 생성 # SQL 명령어를 데이터베이스에 전송하고 결과 받아오기 cursor = conn.cursor() # 생성된 커서를 통해 SQL 쿼리를 실행하고 쿼리 결과를 데이터베이스에서 가져옴. cursor.execute(query) rows = cursor.fetchall() # 쿼리 결과의 모든 행을 가져옴. columns = [desc[0] for desc in cursor.description] # 쿼리 결과의 열 이름을 추출 df = pd.DataFrame(rows, columns=columns) # 쿼리 결과를 데이터프레임으로 변환 cursor.close() conn.close() return df # 문제 및 결과 데이터 생성 problems = ["문1) 구매 금액이 1000원 이상인 회원 이름과 구매물품명, 구매 금액을 조회 하시오.", "문2) 구매 분류가 디지털인 항목을 구매한 회원 명, 전화번호, 구매분류, 물품명, 구매금액을 조회하시오.", "문3) 인원이 6명 이상인 회원이 구매한 물품, 회원명, 회원수, 구매금액을 가격 높은순으로 조회 하시오.", "문4) 가장 비싼 단가를 가진 물품을 구매한 회원의 회원명, 구매단가, 구매물품, 국번전화번호, 평균키, 데뷔 일자를 구하시오. 국번전화번호의 값은 중간에 '-' 으로 연결, 나온 결과값의 정렬은 데뷔 일자가 가장 빠른 순으로 구하시오.", "문5) 키가 165 이하이고 총 구매 금액이 500이 넘는 회원의 회원 아이디, 회원 키, 총구매 금액을 총 구매 수량이 많은 순으로 탑3 까지 조회", "문6) 서울 출생이고 구매하지 않는 회원의 회원 아이디, 데뷔일자를 데뷔 일자가 빠른 순으로 탑2 까지 조회", "문7) 아이즈원은 거제 출생이고, 폰은 없다. 평균키는 170이며 데뷔 날짜및 멤버수는 검색, ID는 IVE 이다.아이즈원은 청바지와 에어팟을 각 3개씩 샀다. insert 하세요.", "문8) 마마무가 자신들의 평균키가 166이라고 정정해달라는 요청이 왔다. 이를 update 하시오.", "문9) 멤버 이름이 4글자인 멤버의 총 평균 키를 조회하시오", "문10) 서적이 모두 환불 되었습니다. 서적을 구매한 회원 네임과 멤버의 전화번호, 환불할 총 구매 금액을 조회 하시오."] results = ["select m.mem_name '회원 이름', b.prod_name '구매물품명', b.price*b.amount '구매 금액' \nfrom member m \nright outer join buy b \non m.mem_id=b.mem_id \nwhere (b.price*b.amount) >=1000;", "select m.mem_name '회원 이름', concat(m.phone1,'/',m.phone2) '전화번호', b.group_name '구매분류', b.prod_name '구매물품명', b.price*b.amount '구매 금액' \nfrom member m \ninner join buy b \non m.mem_id=b.mem_id \nwhere b.group_name='디지털';", "SELECT prod_name, B.mem_id, mem_number, price \nFROM buy B \nINNER JOIN member M \nON B.mem_id = M.mem_id \nWHERE mem_number >= 6 \nORDER BY price DESC;", "SELECT M.MEM_NAME, CONCAT(M.PHONE1, '-', M.PHONE2) AS PHONE, M.HEIGHT, M.DEBUT_DATE, B.PROD_NAME, B.PRICE \nFROM MEMBER M \nINNER JOIN BUY B \nON M.MEM_ID = B.MEM_ID \nWHERE B.price = (SELECT max(price) FROM buy) \nORDER BY M.DEBUT_DATE ASC;", "SELECT B.mem_id, height, SUM(price * amount) \nFROM buy B \nINNER JOIN member M \nON B.mem_id = M.mem_id \nWHERE height <= 165 \nGROUP BY B.mem_id \nHAVING SUM(price) > 500 \nORDER BY COUNT(amount) DESC \nLIMIT 3;", "SELECT DISTINCT M.mem_id, mem_name, debut_date \nFROM member M \nLEFT OUTER JOIN buy B \nON M.mem_id = B.mem_id \nWHERE B.amount IS NULL AND M.addr = '서울' \nORDER BY debut_date ASC \nLIMIT 2;", "insert into member values('IVE','아이즈원', 5,'거제',null,null,170,'2018-10-29'); \ninsert into buy values(null,'IVE','청바지','패션',50,3); \ninsert into buy values(null,'IVE','에어팟','디지털',80,3);", "UPDATE member SET height = 166 \nWHERE mem_name = '마마무';", "SELECT mem_name, AVG(height) \nFROM member \nWHERE mem_name LIKE '____' \nGROUP BY mem_id;", "SELECT M.mem_name '회원 이름', CONCAT(M.phone1, '-', M.phone2) '전화번호', SUM(B.price * B.amount) '환불한 총 금액' \nFROM buy B \nINNER JOIN member M \nON B.mem_id = M.mem_id \nWHERE group_name = '서적' \nGROUP BY M.mem_name, M.phone1, M.phone2;"] class ProblemSelector(QWidget): # 클래스의 생성자로, 이 메서드 내에서 UI를 구성하고 초기화 def __init__(self): # 부모 클래스인 Qwidget의 초기화 메서드를 호출하여 기본 설정 수행 super().__init__() # 창의 제목 설정 self.setWindowTitle("문제 선택기") # 창의 위치와 크기 설정 self.setGeometry(100, 100, 800, 600) # 수직 방향으로 위젯들을 배치, 전체 창의 레이아웃 설정 main_layout = QVBoxLayout() # 문제와 결과를 담은 딕셔너리 생성 data = {'문제': problems, '결과': results} # 딕셔너리를 dataframe으로 변환하여 저장 : 데이터 테이블을 다루는데 유용 self.df = pd.DataFrame(data) # 콤보박스 생성 : 문제 선택 # 수평 방향으로 위젯들을 배치 combo_layout = QHBoxLayout() # 사용자에게 문제를 선택하라는 텍스트 라벨 self.label = QLabel("문제를 선택하세요:") combo_layout.addWidget(self.label) # 문제를 선택할 수 있는 콤보박스 self.combobox = QComboBox() # 문제 목록을 콤보박스에 추가 self.combobox.addItems(problems) combo_layout.addWidget(self.combobox) # 조회 버튼 : 버튼을 눌러 결과 확인 self.button = QPushButton("조회") self.button.clicked.connect(self.show_result) combo_layout.addWidget(self.button) main_layout.addLayout(combo_layout) # 결과 출력 라벨 생성 (QGroupBox) # 결과를 출력할 그룹 박스 self.result_group = QGroupBox("SQL 쿼리 및 결과") result_layout = QVBoxLayout() # SQL 쿼리와 결과를 표시할 텍스트 편집기 생성, 읽기 전용으로 설정 self.result_label = QTextEdit() self.result_label.setReadOnly(True) self.result_label.setFixedHeight(200) # 결과 상자의 높이 조정 result_layout.addWidget(self.result_label) self.result_group.setLayout(result_layout) # 테이블 위젯 생성 (QGroupBox) self.table_group = QGroupBox("쿼리 결과 테이블") table_layout = QVBoxLayout() self.table = QTableWidget() self.table.setFixedHeight(300) # 테이블의 높이 조정 table_layout.addWidget(self.table) self.table_group.setLayout(table_layout) # 메인 레이아웃에 추가 main_layout.addWidget(self.result_group) main_layout.addWidget(self.table_group) self.setLayout(main_layout) def show_result(self): selected_problem = self.combobox.currentText() if selected_problem: # 선택된 문제의 결과를 찾기 result = self.df.loc[self.df['문제'] == selected_problem, '결과'].values[0] # SQL 쿼리를 라벨에 표시 self.result_label.setText(f"선택한 문제: {selected_problem}\n\nSQL 쿼리:\n{result}") if "select" in result.lower(): # 데이터베이스에서 쿼리 결과 가져오기 query_result = get_data_from_database(result) # 테이블 출력 self.table.setRowCount(len(query_result)) self.table.setColumnCount(len(query_result.columns)) self.table.setHorizontalHeaderLabels(query_result.columns) for i in range(len(query_result)): for j in range(len(query_result.columns)): self.table.setItem(i, j, QTableWidgetItem(str(query_result.iat[i, j]))) self.table.resizeColumnsToContents() self.table.resizeRowsToContents() else: # 결과 출력 self.result_label.setText(f"선택한 문제: {selected_problem}\n결과: {result}") if __name__ == "__main__": # pyqt5에서 애플리케이션을 실행하기 위해 필요한 객체 # 모든 pyqt5 애플리케이션은 이 객체를 생성하여 애플리케이션의 컨텍스 설정 # sys.argv : 명령줄 인수를 담고 있는 리스트를 QApplication에 전달하면 커맨드라인 인수를 pyqt5 애플리케이션에서 사용 app = QApplication(sys.argv) # pyqt5 애플리케이션의 메인 윈도우를 정의하는 클래스 # 사용자 인터페이스를 설정하고 이벤트 처리 window = ProblemSelector() # 하위 클래스 인스턴스를 화면에 표시 window.show() # qpplication의 이벤트 루프 시작, 애플리케이션이 종료될 때까지 계속 실행 # sys.exit() : 이벤트 루프가 종료된 후, 애플리케이션의 종료 상태를 반환 # app.exex_() 애플리케이션이 종료될 때까지 계속 실행되며, 종료 상태를 반환 sys.exit(app.exec_()) # 전체적인 흐름 # 애플리케이션 초기화 : QApplication 객체를 생성하여 애플리케이션을 초기화 # 메인 윈도우 생성 : problemselector 클래스를 사용하여 애플리케이션의 메인 창 생성 # 윈도우 표시 : window.show() 메인 창을 화면에 표시 # 이벤트 루프 실행 : app.exec() 이벤트 루프를 시작하고, 애플리케이션이 종료될 때까지 대기 # 종료 처리 : 애플리케이션이 종료되면 sys.exit()으로 종료 상태 반환