테이블에 대한 이벤트에 반응해 자동으로 실행되는 작업을 의미한다. 트리거는 데이터 조작 언어(DML)의 데이터 상태의 관리를 자동화하는 데 사용된다. 트리거를 사용하여 데이터 작업 제한, 작업 기록, 변경 작업 감사 등을 할 수 있다.
일반적으로 트리거는 다음의 3 가지 경우에 시작된다. 트리거는 SELECT 문에 의한 데이터 검색에 영향을 미칠 수 없다.
INSERT (새로운 행 삽입)
UPDATE (기존 행의 변경) / UPDATE OF (기존 행의 특정 열 변경)
DELETE (기존 행 삭제)
ex. 일매출 집계에서 추가삭제/업데이트되는 레코드 자동 계산
https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4_%ED%8A%B8%EB%A6%AC%EA%B1%B0
실행 계획
을 세우고, 최고의 효율을 갖는 실행계획을 판별한 후 그 실행계획에 따라 쿼리를 수행합니다.가 더 맞는 것 같음
DB 설계 튜닝(분석/설계 단계) → DBMS 튜닝(개발/구현 단계) → SQL 튜닝(개발/구현 단계)
DB 설계 튜닝
(모델링 관점)
효율성이 가장 크다
DBMS 튜닝
(환경 관점)
SQL 튜닝
(App 관점)
데이터베이스 튜닝의 3단계
데이터베이스 환경 분석 → 데이터베이스 성능개선 이행 → 데이터베이스 성능개선 평가
http://blog.skby.net/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%8A%9C%EB%8B%9D-db-tuning/
https://travislife.tistory.com/25
https://dlevelb.tistory.com/745
MySQL
SELECT NAME FROM ANIMAL_INS ORDER BY DATETIME LIMIT 1
https://m.blog.naver.com/jwlee0208/10096564579
def solution(record):
record=[re.split(' ') for re in record]
id_nick={}
answer=[]
for re in reversed(record):
if re[1] not in id_nick.keys() and re[0] !='Leave':
id_nick[re[1]]=re[2]
for re in record:
if re[0]=='Enter':
answer.append(id_nick[re[1]]+'님이 들어왔습니다.')
elif re[0]=='Leave':
answer.append(id_nick[re[1]]+'님이 나갔습니다.')
return answer
레코드의 [명령어 아이디 닉네임]이 띄어쓰기로 구분되어 들어오기때문에 문자열을 split해서 하나의 리스트로 만들어주고 전체 레코드 리스트에 다시 넣어준다
id별 마지막 설정한 닉네임은 leave나 change 명령어로 시작하는 레코드에 저장되어있기때문에 레코드를 뒤집어서 뒤에서부터 leave 명령어가 아니고, 이미 저장되어있지 않은 레코드에 대해서만 딕셔너리로 {id:nickname} 저장한다
레코드에 대해서 완성된 화면을 출력한다
테스트 25 〉 통과 (123.43ms, 59.6MB)
테스트 26 〉 통과 (128.40ms, 61.9MB)
테스트 27 〉 통과 (139.65ms, 65.2MB)
테스트 28 〉 통과 (141.08ms, 65.9MB)
테스트 29 〉 통과 (133.99ms, 65.8MB)
테스트 30 〉 통과 (122.53ms, 61.2MB)
테스트 31 〉 통과 (122.02ms, 59.2MB)
테스트 32 〉 통과 (103.76ms, 53.7MB)
변환 횟수가 최소가 되어야하므로 BFS를 써야한다
from collections import deque
def solution(begin, target, words):
answer = 0
q = deque([[begin, 0]]) # 큐 자료구조를 만들어주고 첫번째 노드를 만들어준다 q.append([begin,0])
visited = [ 0 for _ in range(len(words))] # 노드 방문 여부 표시
while q:
word, cnt = q.popleft()
if word == target:
answer = cnt
break
for i in range(len(words)):
temp_cnt = 0
if not visited[i]: # 방문한 적이 없는 노드
for j in range(len(word)):
if word[j] != words[i][j]:
temp_cnt += 1
if temp_cnt == 1:
q.append([words[i], cnt+1])
visited[i] = 1
return answer
collections에서 deque를 임포트한다
deque 객체는 deque([ ])
이렇게 생겨서 첫 줄처럼이 안에 첫번째 노드 값을 그냥 넣어줘도 되고 q.append([begin,0])
이렇게 해도 된다
visited는 노드 방문 여부를 기록한다
큐에서 popleft로 왼쪽 노드 값을 꺼내서 word, cnt에 언패킹한다
만약 이 단어가 타겟 단어라면 cnt를 answer에 넣고 반복문을 벗어나서 answer를 리턴하게 된다
begin이 target과 다르다면 다음 for문을 진행한다.
전체 단어목록의 크기의 인덱스 i에 대해서 temp_cnt를 생성해준다.
방문한 적이 없는 노드에 대해서 단어(최초에는 begin)의 길이 인덱스 j를 이용해서 begin과 words의 i번째 단어의 각 자리 알파벳을 비교한다.
만약 다르다면 temp_cnt에 1을 넣어준다
temp_cnt==1일 때 한자리만 다르기 때문에 변환 가능한 단어가 되어서 큐에 넣어줄 수 있고 해당 순번 노드에 방문 표시를 한다
# begin="hit" ; target="cog"
# words=["hot", "dot", "dog", "lot", "log", "cog"]
q: deque([['hot', 1]])
q: deque([['dot', 2], ['lot', 2]]) # begin과 한자리만 다른 단어들
q: deque([['lot', 2], ['dog', 3]]) # popleft로 왼쪽 값이 먼저 삭제됨
q: deque([['dog', 3], ['log', 3]]) # 그 다음 값은 자동으로 왼쪽으로 이동
q: deque([['log', 3], ['cog', 4]])
q: deque([['cog', 4]])
4 # return 값
통과를 못하긴 했지만 풀다보니 큐를 사용한 BFS 구현 코드랑 비슷하게 나왔던 게 진짜 신기했다 담엔 큐로 잘 풀 수 있으면 좋겠다
from collections import deque
리스트랑 똑같이 생겼다고 생각하면 됨 트리아님
리스트의 extend()
reverse()
insert(위치, 값)
remove(값)
사용 가능
append()
pop()
appendleft()
popleft()
append()
pop()
https://dongdongfather.tistory.com/72
https://hellominchan.tistory.com/156
my_info = ['lee', '30', 'seoul', '010', 'xxxx', 'yyyy']
name, age, address, *unknowns = my_info
print(name) # lee
print(age) # 30
print(address) # seoul
print(unknowns) # ['010', 'xxxx', 'yyyy']
https://itholic.github.io/python-pack-unpack-1/
import collections
def solution(str1, str2):
# 배열 만들기
str1_list,str2_list=[],[]
for i in range(len(str1)-1):
if str1[i:i+2].isalpha():
str1_list.append(str1[i:i+2].lower())
for i in range(len(str2)-1):
if str2[i:i+2].isalpha():
str2_list.append(str2[i:i+2].lower())
# 모두 공집합일 경우 1 리턴
if str1_list==[] and str2_list==[]:
return 65536
# 빈도 카운트 및 계산
counter_1=collections.Counter(str1_list)
counter_2=collections.Counter(str2_list)
numerator,denominator=0,0
for i in (set(str1_list)&set(str2_list)):
numerator+=min(counter_1[i],counter_2[i])
for i in (set(str1_list)&set(str2_list)):
denominator+=max(counter_1[i],counter_2[i])
for u in (set(str1_list)-(set(str2_list))):
denominator+=counter_1[u]
for u in (set(str2_list)-(set(str1_list))):
denominator+=counter_2[u]
return int((numerator/denominator)*65536)
버림은 int로 구현할 수 있다
+배열 여러 개를 한번에 만드는 방법을 봤던 것 같은데 다시 찾아봐야지.. 이거 코드가 너무 창피하다 ㅠㅠ
✔️아래 3줄을 그냥 합집합으로 할 수 있다
나 첨에 합집합으로 했는데 왜 뭐 오류났겠지 또 .. 그래서 이것저것 수정하다가 이렇게 된듯.. 들고가기 전에 꼭 다시한번 고쳐봐야지 ㅠㅠ
for u in (set(str1_list)|(set(str2_list))):
denominator+=max(counter_1[i],counter_2[i])
윗 부분도 리스트 축약식으로 바꾸면 더 간략하게 쓸 수 있다
축약식을 쓰면 먼저 빈 집합으로 선언하지 않아도돼서 더더 간략해진다
꼭 다시 해보고 가야지 흐
import collections
def solution(str1, str2):
str1_list=[str1[i:i+2].lower() for i in range(len(str1)-1) if str1[i:i+2].isalpha()]
str2_list=[str2[i:i+2].lower() for i in range(len(str2)-1) if str2[i:i+2].isalpha()]
if str1_list==[] and str2_list==[]:
return 65536
counter_1=(collections.Counter(str1_list))
counter_2=(collections.Counter(str2_list))
numerator,denominator=0,0
for i in (set(str1_list)&set(str2_list)):
numerator+=min(counter_1[i],counter_2[i])
for u in (set(str1_list)|set(str2_list)):
denominator+=max(counter_1[u],counter_2[u])
return int((numerator/denominator)*65536)
아래도 그냥 축약식으로 바꾸자..
import collections
def solution(str1, str2):
str1_list=[str1[i:i+2].lower() for i in range(len(str1)-1) if str1[i:i+2].isalpha()]
str2_list=[str2[i:i+2].lower() for i in range(len(str2)-1) if str2[i:i+2].isalpha()]
if str1_list==[] and str2_list==[]: #len(set1|set2) 해도 되네 진짜..
return 65536
counter_1=(collections.Counter(str1_list))
counter_2=(collections.Counter(str2_list))
numerator=sum([min(counter_1[i],counter_2[i]) for i in (set(str1_list)&set(str2_list))])
denominator=sum([max(counter_1[u],counter_2[u])for u in (set(str1_list)|set(str2_list))])
return int((numerator/denominator)*65536)
if str1_list==[] and str2_list==[]:
이 부분도 빈 배열이면 False니까 if not str1_list and not str2_list:
이렇게 해도 되고
len(set1|set2)
해도 된다 역시 리팩토링을 꼭 해야한다