오늘은
요즘엔 일교차가 꽤나 심한 것 같습니다
아침과 저녁에는 춥고 낮에는 햇빛 덕에 따뜻해서
냉탕과 온탕을 왔다갔다하는 느낌입니다
그래서 그런지 집에오면 다른 때보다 부쩍 피곤한것같습니다
목표치를 최대한 채워보려고 노력중인데
지장이 생기지 않도록 컨디션 관리에 신경을 써주어야겠습니다
학원 수업
<<SQL>>
연산자
=, <>(!=), >=, <= : 같다 같지않다 크다 작다
BETWEEN, AND : 범위(이상 이하)
IN(A, B, C) : 포함(조건값이 명확)
LIKE : 조회(조건 값이 불명확) % 사용 <-> NOT LIKE 포함되지 않은 것
IS NULL : 데이터 값이 NULL인 경우 <-> is NOT NULL
통계 함수
COUNT : 개수
SUM : 합계
AVG : 평균
MAX : 최대값, MIN : 최소값
GROUP BY : 그룹화
HAVING : GROUP BY 절에 조건이 있는 경우 => 그룹을 제한하는 역할
select * from orders;
-- 주문 테이블의 칼럼과 자료형 구조 보기
DESC orders;
-- 통계 함수 (개수-COUNT, 합계-SUM, 평균-AVG, 최대값-MAX, 최소값-MIN)
SELECT COUNT(orderid) AS 총판매건수
FROM orders;
-- COUNT(*) = '*' 모든 칼럼
-- COUNT(칼럼명) = 특정 칼럼
SELECT SUM(saleprice) AS 총판매액,
AVG(saleprice) AS 총평균액
FROM orders;
SELECT COUNT(*) AS 총고객수, COUNT(phone) AS 전화번호수
FROM customer;
-- 고객이 주문한 도서의 총판매액 계산
SELECT SUM(saleprice) AS 총판매액
FROM orders;
-- 고객별로 주문한 도서의 총판매액을 계산
-- 그룹으로 묶을 때 사용 - GROUP BY 칼럼명
-- 도서수량이 3권이상인 자료 검색
-- GROUP BY절에서 조건이 있는 경우 = HAVING 사용
SELECT custid,
COUNT(*) AS 도서수량,
SUM(saleprice) AS 총판매액
FROM orders
GROUP BY custid
HAVING COUNT(*) >= 3
AND SUM(saleprice) >= 35000;
-- 도서중에서 최대가격, 최저가격 알기
SELECT MAX(price) 최고가격, MIN(price) 최저가격
FROM book;
-- 고객 출력
SELECT * FROM customer;
-- '3번 고객(안산)'이 주문한 도서의 총 판매액 구하기
SELECT sum (saleprice) as 총판매액
FROM orders
WHERE custid = 3;
-- 조인(JOIN)
-- 동등조인(EQUI HOIN = equal(=)을 사용하는 조인
-- 테이블A,칼럼명 = 테이블B.칼럼명 (칼럼 = 외래키)
-- 고객의 이름과 고객이 주문한 주문가격을 검색하시오
SELECT customer.name, orders.saleprice
FROM customer, orders
WHERE customer.custid = orders.custid;
-- 별칭 사용 조인
-- 고객 이름별 1차 정렬(오름차순), 주문 가격별 내림차순 2차 정렬
SELECT cus.name, ord.saleprice
FROM customer cus, orders ord
WHERE cus.custid = ord.custid
ORDER BY cus.name, ord.saleprice desc;
-- 3번 고객의 아이디와 도서 이름과 주문 가격 검색
SELECT custid, bookname, saleprice
FROM orders, book
WHERE orders.bookid = book.bookid
AND orders.custid = 3;
COMMIT;
* 뷰
DB
CREATE USER
CREATE TABLE
CREATE VIEW(뷰)
= 하나 이상의 테이블을 합하여 만든 가상의 테이블로써
실제 테이블처럼 이용할 수 있는 데이터베이스 개체이다
뷰를 생성하는 방법
CREATE VIEW 뷰이름
AS SELECT문
-- 뷰(VIEW)
-- UPDATE, DELETE가능(하지만 제약이 있다), INSERT INTO불가능
-- 주소에 '대한민국'을 포함하는 고객들로 구성된 뷰를 만드시오
CREATE VIEW vw_customer
AS SELECT * FROM customer
WHERE address LIKE '대한민국%';
SELECT * FROM vw_customer;
-- 이름이 김연아를 신유빈으로 변경
UPDATE vw_customer
SET name = '신유빈'
WHERE name = '김연아';
-- 고객아이디가 '3'인 고객을 삭제
-- 참조하고 있는 order 테이블이 있어서 삭제 불가
DELETE FROM vw_customer
WHERE custid = 3;
COMMIT;
-- VIEW 삭제
DROP VIEW vw_customer;
* 조인(JOIN)
표준 조인(standard join) - ANSI JOIN
INNER KOIN ~ ON(FROM절에서 사용
-- 조인 : 두 테이블을 연결하여 사용하는 기법
-- 동등조인(EQUI) : 조인 조건이 정확히 일치하는 경우에 결과 출력
-- 외부조인(OUTER) : 조인 조건이 정확히 일치하지 않아도 모든 결과를 출력
-- 고객(customer)과 고객의 주문(oreders)에 관한 데이터를 모두 검색하시오
-- 고객이름으로 정렬(자동으로 그룹화 됨)
SELECT cus.name, ord.saleprice
FROM customer cus, orders ord
WHERE cus.custid = ord.custid -- 동등조인
ORDER BY cus.name;
-- 고객(customer)과 고객의 주문(oreders)에 관한 데이터를 모두 검색하시오
-- 조건 => '박지성' 고객의 주문내역을 검색하시오
SELECT cus.name, ord.saleprice
FROM customer cus, orders ord
WHERE cus.custid = ord.custid
AND cus.name = '박지성'
ORDER BY ord.saleprice;
-- 고객(customer)과 고객의 주문(oreders)에 관한 데이터를 모두 검색하시오
-- 고객별 주문 금액의 총액 출력(GROUP BY 결과)
-- 김연아 고객의 주문 총금액을 출력(HAVING으로 제한을 둠)
SELECT cus.custid, cus.name, SUM(ord.saleprice)
FROM customer cus, orders ord
WHERE cus.custid = ord.custid
-- AND cus.name = '김연아'
GROUP BY cus.custid, cus.name -- SELECT와 GROUP BY 동기화 필요
HAVING cus.name = '김연아'
ORDER BY cus.name;
-- 주문하지 않은 데이터도 모두 검색
-- 조건이 일치하지 않은 테이블에 +를 넣어줌
SELECT cus.name, ord.saleprice
FROM customer cus, orders ord
WHERE cus.custid = ord.custid(+) -- 외부조인 => orders쪽에서 주문하지 않은 고객까지 출력
ORDER BY cus.name;
-- 고객의 이름, 주문한 도서 이름, 주문일, 주문금액
SELECT cus.name, bk.bookname, ord.orderdate, ord.saleprice
FROM customer cus, book bk, orders ord
WHERE cus.custid = ord.custid -- 기본키 = 외래키
AND bk.bookid = ord.bookid
ORDER BY cus.name;
-- 표준 조인(ANSI SQL)
-- 내부 조인(INNER JOIN)
-- 고객(customer)과 고객의 주문(oreders)에 관한 데이터중
-- 고객의 이름과 고객이 주문한 도서의 판매가격을 검색하시오
SELECT cus.name, ord.saleprice
FROM customer cus INNER JOIN orders ord
ON cus.custid = ord.custid -- 동등조인
ORDER BY cus.name;
-- 외부 조인(OUTER JOIN)
-- 고객(customer)과 고객의 주문(oreders)에 관한 데이터중
-- 주문되지 않은 데이터를 포함하여 고객의 이름과 고객이 주문한 도서의 판매가격 검색
SELECT cus.name, ord.saleprice
FROM customer cus LEFT OUTER JOIN orders ord -- 테이블 기준에 따라 LEFT, RIGHT가 달라진다
ON cus.custid = ord.custid(+) -- 외부조인 => orders쪽에서 주문하지 않은 고객까지 출력
ORDER BY cus.name;
COMMIT;
<<JAVA>>
회원 - users(Entity)
아이디, 이름, 비밀번호, 나이, 이메일
userid, username, userpassword, userage, useremail
게시판 - boards
글번호, 글제목, 글내용, 작성자, 작성일, 파일이름, 파일내용(경로)
bno, btitle, bcontent, bwriter, bdate, bfilename, bfiledata
자동순번 - 시퀀스(sequence)
CREATE SEQUENCE seq_bno NOCACHE
package domain;
import java.io.Serializable;
import java.sql.Blob;
import java.util.Date;
//DTO(VO) 클래스 = 자료 전달 객체
public class Board implements Serializable {
private static final long serialVersionUID = 1111L;
private int bno;
private String btitle;
private String bcontent;
private String bwriter;
private Date bdate;
private String bfileName;
private Blob bfileData;
public int getBno() {
return bno;
}
public void setBno(int bno) {
this.bno = bno;
}
public String getBtitle() {
return btitle;
}
public void setBtitle(String btitle) {
this.btitle = btitle;
}
public String getBcontent() {
return bcontent;
}
public void setBcontent(String bcontent) {
this.bcontent = bcontent;
}
public String getBwriter() {
return bwriter;
}
public void setBwriter(String bwriter) {
this.bwriter = bwriter;
}
public Date getBdate() {
return bdate;
}
public void setBdate(Date bdate) {
this.bdate = bdate;
}
public String getBfileName() {
return bfileName;
}
public void setBfileName(String bfileName) {
this.bfileName = bfileName;
}
public Blob getBfileData() {
return bfileData;
}
public void setBfileData(Blob bfileData) {
this.bfileData = bfileData;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
@Override
public String toString() {
return "Board [bno=" + bno + ", btitle=" + btitle + ", bcontent=" + bcontent + ", bwriter=" + bwriter
+ ", bdate=" + bdate + ", bfileName=" + bfileName + ", bfiledData=" + bfileData + "]";
}
}
package dbcrud;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import domain.Board;
public class BoardSelectTest {
public static void main(String[] args) {
Connection conn = null; // 네트워크 연결 클래스
PreparedStatement pstmt = null; // sql을 처리해주는 인터페이스
try {
// JDBC 드라이버 등록
Class.forName("oracle.jdbc.OracleDriver");
// 연결하기 - getConnection(url, user, password)
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521/xe",
"c##mydb",
"pwmydb");
System.out.println("연결 성공!");
// db 처리 작업
// 매개변수화된 sql문 작성 - 동적 바인딩
String sql = "SELECT * FROM boards WHERE bwriter = ? "
+ "ORDER BY bno DESC";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "sky123");
ResultSet rs = pstmt.executeQuery(); // sql 실행
List<Board> boardList = new ArrayList<>();
while(rs.next()) {
Board board = new Board();
board.setBno(rs.getInt("bno"));
board.setBtitle(rs.getString("btitle"));
board.setBcontent(rs.getString("bcontent"));
board.setBwriter(rs.getString("bwriter"));
board.setBdate(rs.getDate("bdate"));
board.setBfileName(rs.getString("bfilename"));
board.setBfileData(rs.getBlob("bfiledata"));
boardList.add(board);
// 서버 컴퓨터의 하드디스크에 첨부 파일 저장
Blob blob = board.getBfileData();
if(blob != null) {
InputStream is = blob.getBinaryStream();
OutputStream os = new FileOutputStream("C:/File/" + board.getBfileName());
byte[] data = new byte[1024];
while(true) {
int num = is.read(data);
if(num == -1) break;
os.write(data, 0, num);
}
os.flush();
os.close();
is.close();
}
}
// boardList 출력
for(Board board : boardList) {
System.out.println(board);
}
rs.close();
pstmt.close();
} catch (Exception e) {
e.printStackTrace();
} finally{ // 반드시 수행되는 구간
if(conn != null) { // 연결이 되어 있다면
try {
conn.close();
System.out.println("연결 끊음");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
HTML 공부
<<HTML 폼>>
<label>요소
접근성과 폼을 쓰기 편하게 해준다
실제로 특정한 입력값이나 Form control, 텍스트와 직접적으로 연결되어 있다
두 요소를 연결 시 레이블 자체를 클릭할 수 있게도 해준다
=> 작은 스크린 기기에서나 시력이 안 좋은 사람에겐 더 유용함
* 레이블과 입력값 간의 연결
<input id="">
<input>태그 안에 ID를 입력 -> <label>태그의 for 속성에 지정
=> 무엇을 정의하는지, 무엇을 위한 건지 나타내준다
=> 한 페이지에서는 한개의 요소만 지정된 ID를 지녀야 한다
= 다른 아이디를 써도 되지만 같은 ID를 다시 사용해서는 안된다
그래야 정확히 하나의 입력값에만 레이블을 지정할 수 있기 때문
->
<form action="/tacos">
<p>
<label for="uername"> Enter a Username:</label>
<input id="username" type="text" palceholder="username">
</p>
<p>
<label for="password"> Enter a Password:</label>
<input type="password" palceholder="password" id="password">
</p>
<p>
<label for="color"> Enter a Color:</label>
<input type="color" id="color">
</p>
<p>
<label for="number"> Enter a Number:</label>
<input type="number" palceholder="enter a number" id="number">
</p>
</form>
=> 페이지내의 텍스트를 클릭하면 username 칸에 입력을 할 수 있게 해준다
= 둘이 서로 연결되어 있다는 것
<button>요소
여는 태그와 닫는 태그가 있다
그 안에 입력하는 모든 텍스트 -> 버튼에 레이블을 지정하게 된다
CSS를 활용하여 버튼을 바꿔줄 수 있다
-> 폼의 끝 부분에 <button> 추가
-> 버튼을 클릭하면 폼이 제출된다
-> 폼 밖에 버튼을 만들면 아무리 눌러도 작동하지 않는다
=> type 사용 옵션 지정
<button type="button"> </button>
= 폼을 제출하는 버튼이 아니라 오직 버튼으로만 기능하게 한다
=> 버튼이 폼 안에 있을 때의 기본값으 submit이다
=> type가 submit인 <input>
<input type="submit"> 과 <button> Submit</button> 은
똑같아 보이는 버튼을 각각 생성한다
하지만 <input>태그는 닫는 태그가 없기 때문에 내부 속성에서 내용을 변경해주어야 하고
<button>태그는 여는 태그와 닫는 태그 사이의 내용을 그냥 바꿔주기만 하면 된다
* 입력값에 매우 중요한 name 속성
= 데이터가 서버로 전송될 때 <input>안에 있는 값을 지칭하기 위한 것
= 보통 공백이 없고 짧다 => 서버가 찾으려는 간단한 값
=> <input>중 아무 곳에나 name을 추가
-> 입력하고 폼을 제출
= 데이터를 서버로 전송할 때 사용되는 name이 된다
= 'name=값' 의 형태라고 생각하면 된다
=> 모든<input>에 name을 다 넣어야 한다 = 결국 서버로 데이터를 전송할 때 사용하게 되기 때문
Coding Test Practice
Description
1부터 13까지의 수에서, 1은 1, 10, 11, 12, 13 이렇게 총 6번 등장합니다. 정수 i, j, k가 매개변수로 주어질 때, i부터 j까지 k가 몇 번 등장하는지 return 하도록 solution 함수를 완성해주세요.
function solution(i, j, k) {
var answer = '';
var count = 0;
for(i; i <= j; i++){
answer+=i;
}
for(var i = 0; i < answer.length; i++){
if(answer[i] == k){
count++;
}
}
return count;
}
i부터 j까지의 수를 담을 문자열을 선언해서
구분없이 모든 숫자를 문자로써 합쳐버린 후에
k와 같은 요소가 나올때마다 count를 세어주어 해결
Description
문자열 my_string이 매개변수로 주어집니다. my_string은 소문자, 대문자, 자연수로만 구성되어있습니다. my_string안의 자연수들의 합을 return하도록 solution 함수를 완성해주세요.
function solution(my_string) {
var answer = 0;
var numbers = my_string.match(/\d+/g);
if(numbers != null){
for(var i = 0; i < numbers.length; i++){
answer += Number(numbers[i]);
}
}else{
return 0;
}
return answer;
}
정규표현식을 사용하여 해결
정규표현식 \d+에서 +는 "한 번 이상 반복"을 나타내는 메타문자
\d는 하나의 숫자에 대응, +는 연속된 숫자도 찾아내라는 의미
Description
문자열 myString과 pat이 주어집니다. myString에서 pat이 등장하는 횟수를 return 하는 solution 함수를 완성해 주세요.
function solution(myString, pat) {
var answer = 0;
var patLeng = pat.length;
var part = '';
for (let i = 0; i <= myString.length - patLeng; i++) {
part = myString.substr(i, patLeng);
if (part === pat) {
answer++;
}
}
return answer;
}
substr()함수 = i부터 patLeng까지 길이의 부분 문자열을 추출
추출된 문자열과 pat이 일치하는지 비교해서 횟수를 세어주어 해결
2023. 10. 12 (목)
프로그래머 도전기 45일차 (2) | 2023.10.15 |
---|---|
프로그래머 도전기 44일차 (3) | 2023.10.14 |
프로그래머 도전기 42일차 (4) | 2023.10.12 |
프로그래머 도전기 41일차 (0) | 2023.10.11 |
프로그래머 도전기 40일차 (0) | 2023.10.09 |