의료 IT를 할때는 오라클을 썼는데, SM근무를 하며 병원통계기록을 뽑아줄때 select 쿼리를 참 많이 사용했었다. 지금은 frontend로 커리어 전환을 하려다보니 쿼리를 안써버릇해서 다시 공부중이다. mysql로 공부를 하려고 하다 아래 사이트를 찾았는데 공부하기 좋은 사이트 같다.
https://www.mysqltutorial.org/
mySQL은 빌트인 BOOLEAN
타입을 가지고 있지 않다. 대신 TINYINT(1)
를 BOOLEAN
으로 사용한다. 1은 참, 0은 거짓
'0000-00-00'은 is null
에 대응된다.
select cast('0000-00-00' as date) is null // 1
mySQL의 @@sql_auto_is_null
의 디폴트는 0이다. 이것이 만약 1로 세팅이 되고 is null 조건에 의해 조회를 하면 auto_increment column
이 입력되고 마지막으로 성공한 값을 조회한다.
표준 SQL의 일반적인 evaluate 뒤는 순서는 아래와 같다.
FROM > WHERE > GROUP BY > HAVING > SELECT > ORDER BY > LIMIT
하지만 mySQL의 evaluate 순서는 아래와 같다. 관련이유 링크(ONLY_FULL_GROUP_BY)
FROM > WHERE > SELECT > GROUP BY > HAVING > ORDER BY > LIMIT
select절에서 ALIAS를 컬럼에 사용한다.
mySQL에서는 group by
, having
에도도 알리아스를 사용할 수 있다.
WHERE
에서는 못쓴다. 왜냐하면 WHERE
는 SELECT 절이 평가되기전에 실행되기 때문에...그럼 MYSQL에서는 왜 GROUP BY
, HAVING
에서는 쓸 수 있을까?
mysql의 ONLY_FULL_GROUP_BY
기능과 관련이 있는데 스탠다드한 ALIAS 사용을 원한다면 sql_mode
에서 ONLY_FULL_GROUP_BY
를 설정하면 된다.
SET [SESSION | GLOBAL] sql_mode = ONLY_FULL_GROUP_BY;
그럼 group by와 having에서 별칭을 사용할 수 없다.
테이블에도 ALIAS를 사용할 수 있는데 조인시에 동일한 컬럼이 있을 때 어느 테이블을 가리키는지 명확히 하기 위해서이다.
mySQL에서는 full outer join을 지원하지 않는다.
join시에 비교하는 컬럼이 같은 컬럼명이면 using을 쓸수있고 on으로 했을 때와 동일하다.
-- on 사용시
SELECT
m.member_id,
m.name member,
c.committee_id,
c.name committee
FROM
members m
INNER JOIN committees c
ON c.name = m.name;
-- using 사용시
SELECT
m.member_id,
m.name member,
c.committee_id,
c.name committee
FROM
members m
INNER JOIN committees c USING(name);
table a를 기준으로 b를 left조인 한다고 하자.
select
...
from
table a,
left join table b on a.id = b.id
left 조인(left outer 조인) right 조인(right outer 조인)은 기준이 되는 테이블의 데이터 전부를 대상
조건과 맞는 데이터를 조회
b에서 해당하는 데이터는 null데이터로 조회
한다. 즉 left 조인 right 조인에서 on에 해당하는 조건은 조회가 될 데이터가 나오느냐 null로 된 데이터가 나오느냐의 차이일 뿐 기준테이블의 모든 데이터를 다 대상으로 row가 조회된다.
하지만 where 절에서 조건을 건다면 기준테이블의 모든 데이터를 다 대상으로 row를 조회하지 않고 where조건에 맞는 것들만 대상으로 한다.
inner 조인에서는 on에 걸든 where에 걸든 조회결과는 같다.
크로스 조인은 조건이 없는 조인이라고 생각하면된다. 따라서 각 테이블의 row수만큼 n x m 개의 행이 만들어진다. 즉 모든 조건에 대응되는 조인이며 이때 where을 사용해서 조건을 추가하면 inner join과 같다.
group by
는 컬럼이나 표현식의 값을 기준으로 행집합을 요약행집합으로 그룹화한다. 즉 각 gruop에 대해 하나의 행을 반환한다.
ℹ️ aggregate function
: sum
,avg
,max
,min
,count
등의 집계함수
group by
와 having
에 alias를 사용할 수 있다.group by
에 desc을 사용할 수 있다.하나의 쿼리에서 두개 이상의 그룹화 집합을 함께 생성하려면 union all
을 사용할 수 있다. 하지만 두개의 문제가 있다.
이때 사용하는게 with rollup
이다.
SELECT
productLine,
orderYear,
SUM(orderValue) totalOrderValue
FROM
sales
GROUP BY
productline,
orderYear
WITH ROLLUP;
rollup은 부분합 행에 대해서 그룹핑을 해준다.
grouping()
함수는 supper-aggregate row
에서 null
이면 1을 리턴, 아닌경우 0을 리턴한다.
grouping()
함수는 select
,having
,order by
에서 사용할 수 있다.
rollup
을 사용함으로서 발생한 null에 대응할수 있는 함수이다.
select
if(grouping(orderyear), 'ALL YEARS', orderYear) orderyear,
if(grouping(productLine), 'ALL PRODUCTLINES', productLine) productLine,
sum(orderValue) totalOrderValue
from
sales
group by
orderYear,
productline
with rollup;
mySQL의 8.0 버전이상에만 사용가능하다.
재귀 CTE는 CTE 이름 자체를 참조하는 하위쿼리가 있는 CTE이다.
재퀴 CTE는 아래와 같은 형태로 만들어진다.
WITH RECURSIVE cte_name AS (
initial_query -- anchor member
UNION ALL
recursive_query -- recursive member that references to the CTE name
)
SELECT * FROM cte_name;
ℹ️ 실행순서
ℹ️ 재귀멤버 제한
재귀멤버는 다음 구성을 포함하지 않아야한다.
앵커멤버에는 적용되지 않는다.
exists
는 실행결과가 있으면 true, 없으면 false를 리턴한다. 즉 최소한의 결과가 있는지 여부만 확인되면 스캔을 멈추기 때문에 일반적으로 in
보다 빠르다.
하지만 in
을 사용시 결과가 적다면 in
이 더 빠를 수 있다.
SQL의 표준 세집합 연산자는 UNION
,INTERSECT
,MINUS
이다.
mySQL은 MINUS
연산자를 지원하지 않는다. 대신 LFET JOIN
절을 사용해서 MINUS와 동일한 결과를 반환한다.
mySQL은 INTERSECT
연산자를 지원하지 않는다. 대신 INNER JOIN
과 DISTINCT
를 사용하거나 DISTINCT
와 하위쿼리를 사용해서 결과를 동일하게 얻을 수 있다.