sql - GradedJestRisk/db-training GitHub Wiki

SQL

SQL, Structured Query Language, is a standard.

SQL does not apply only to relational database. It is a data query language (data themselves doesn't have to be stored in ACID-enforcing system).

Standard is not free and is difficult to read, so consider :

DDL

Data definition language

DML

Data manipulation language

?

Data ? Language

  • UPDATE
  • INSERT
  • DELETE
  • MERGE

DQL

Data Query Language:

  • SELECT

COUNT

SELECT COUNT(*) 
FROM table
SELECT field, COUNT(*) 
FROM table
GROUP BY field

COUNT(field) count the rows of the dataset, whose value is not the NULL value

COUNT(*) count the rows of the dataset

NULL

If a field contains NULL, DO NOT filter it without IS (NOT) NULL condition.

DO NOT DO THIS!!

AND field <> 1

DO THIS

AND IS NOT NULL AND field1 <> 1

Using vendor-alternatives, like NVL() in Oracle may cause problems because of special values eg: NVL(field1, 0, field1) <> 1

It may work now, but as soon as developer will use 0 in a row, it will break..

WITH

Source

Difference with subqueries:

  • readibility;
  • performance.

Also, avoid switching to procedural (than can imply performance loss) because of query complexity without it.

Example

For each employee:

  • manager name;
  • how many other people are in their department ?

Inline view

SELECT e.ename AS employee_name,
       dc1.dept_count AS emp_dept_count,
       m.ename AS manager_name,
       dc2.dept_count AS mgr_dept_count
FROM   emp e
       JOIN (SELECT deptno, COUNT(*) AS dept_count
             FROM   emp
             GROUP BY deptno) dc1
         ON e.deptno = dc1.deptno
       JOIN emp m ON e.mgr = m.empno
       JOIN (SELECT deptno, COUNT(*) AS dept_count
             FROM   emp
             GROUP BY deptno) dc2
         ON m.deptno = dc2.deptno;

Using a WITH clause

WITH dept_count AS (
  SELECT deptno, COUNT(*) AS dept_count
  FROM   emp
  GROUP BY deptno)
SELECT e.ename AS employee_name,
       dc1.dept_count AS emp_dept_count,
       m.ename AS manager_name,
       dc2.dept_count AS mgr_dept_count
FROM   emp e
       JOIN dept_count dc1 ON e.deptno = dc1.deptno
       JOIN emp m ON e.mgr = m.empno
       JOIN dept_count dc2 ON m.deptno = dc2.deptno;

So we don't need to redefine the same subquery multiple times. Instead we just use the query name defined in the WITH clause, making the query much easier to read.

If the contents of the WITH clause is sufficiently complex, Oracle may decide to resolve the result of the subquery into a global temporary table. This can make multiple references to the subquery more efficient

Can use multiple subqueries using renaming

WITH 
   src_done  AS (SELECT id FROM source WHERE status = 'DONE'),
   src_valid AS (SELECT id FROM source WHERE status <> 'CANCEL' AND cancel_date < SYSDATE)
SELECT
(...)
FROM data
WHERE data.id IN (src_done.id, src_valid.id) 

Can use it including INSERT INTO

INSERT INTO <TARGET TABLE>
WITH 
   source AS (.. FROM <SOURCE>..)
SELECT
(..)
FROM 
   <INTERMEDIATE> INNER JOIN source (..)

Joins

These are equivalent, but ON doesn't work if:

  • column names are not the same in the two tables;
  • you want to use the joining column in SELECT
SELECT e.ename, d.dname
FROM emp e JOIN dept d USING (deptno);

SELECT e.ename, d.dname
FROM emp e JOIN dept d ON d.deptno = e.deptno;

DCL

Data Control Language

Grant, REVOKE

⚠️ **GitHub.com Fallback** ⚠️