SQLでデータを除く方法についてまとめています。
SQLの「除く」指定は、not in 指定データ群を除外する
SQLで、特定の値を持つレコードを除外するにはnot inを使用します。
SELECT * FROM `departments` WHERE dept_name NOT IN ( 'Sales', 'Development' ); +---------+--------------------+ | dept_no | dept_name | +---------+--------------------+ | d009 | Customer Service | | d002 | Finance | | d003 | Human Resources | | d001 | Marketing | | d004 | Production | | d006 | Quality Management | | d008 | Research | +---------+--------------------+
上記の例は、departments(部署テーブル)から、dept_name(部署名)がSalesまたはDevelopmentの部署を除いてデータを取得する例です。
【関連記事】
▶SQL not in データの除外指定 NULLや複数カラムを扱う方法
単純に重複を除くには、distinct
重複したレコードを除いてデータを取得するには、distinctを使います。
SELECT distinct dept_name, title FROM `titles` left join dept_emp on titles.emp_no = dept_emp.emp_no left join departments on dept_emp.dept_no = departments.dept_no order by dept_name,title; --------------------+--------------------+ | dept_name | title | +--------------------+--------------------+ | Customer Service | Assistant Engineer | | Customer Service | Engineer | | Customer Service | Manager | | Customer Service | Senior Engineer | | Customer Service | Senior Staff | | Customer Service | Staff | | Customer Service | Technique Leader | | Development | Assistant Engineer | | Development | Engineer | | Development | Manager | | Development | Senior Engineer | : :
上記の例は、titles(役職)テーブルから、部署(departments)ごとに存在する役職を重複を除いて取得する例です。
distinct dept_name, titleのように指定すると複数のカラムを組み合わせたときの重複をを除きます。
【関連記事】
▶SQL distinctのサンプルコード集 group byよりも700倍速い?
「除く」対象が動的に変わる場合は、サブクエリを使用
除く対象が動的に変わるケースでは、サブクエリを組み合わせます。
例えば以下のように、サブクエリの結果に対してnot inによる条件指定を行います。下記SQLは、first_name(姓名の名)がGeorgiのレコードをサブクエリで取得し、メインクエリでサブクエリの結果を除いたレコードを取得しています。
mysql> select * from employees a where first_name not in (select first_name from employees b where first_name = 'Georgi' ); +--------+------------+------------+-----------+--------+------------+ | emp_no | birth_date | first_name | last_name | gender | hire_date | +--------+------------+------------+-----------+--------+------------+ | 10002 | 1964-06-02 | Bezalel | Simmel | F | 1985-11-21 | | 10003 | 1959-12-03 | Parto | Bamford | M | 1986-08-28 | | 10004 | 1954-05-01 | Chirstian | Koblick | M | 1986-12-01 | | 10005 | 1955-01-21 | Kyoichi | Maliniak | M | 1989-09-12 | | 10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 | | 10007 | 1957-05-23 | Tzvetan | Zielinski | F | 1989-02-10 | | 10008 | 1958-02-19 | Saniya | Kalloufi | M | 1994-09-15 | | 10009 | 1952-04-19 | Sumant | Peac | F | 1985-02-18 | | 10010 | 1963-06-01 | Duangkaew | Piveteau | F | 1989-08-24 | | 10011 | 1953-11-07 | Mary | Sluis | F | 1990-01-22 | : :
上記は、値を直接not inに指定してもできるケースです。
応用すると、以下の例のように「同じデータが1件以上存在するレコードを除く」指定が可能になります。
select * FROM salaries a WHERE (emp_no, to_date) not in ( select emp_no, max(to_date) as to_date from salaries b where a.emp_no = b.emp_no group by emp_no having count(*) > 1 ); +--------+--------+------------+------------+ | emp_no | salary | from_date | to_date | +--------+--------+------------+------------+ | 10001 | 60117 | 1986-06-26 | 1987-06-26 | | 10001 | 62102 | 1987-06-26 | 1988-06-25 | | 10001 | 66074 | 1988-06-25 | 1989-06-25 | | 10001 | 66596 | 1989-06-25 | 1990-06-25 | | 10001 | 66961 | 1990-06-25 | 1991-06-25 | | 10001 | 71046 | 1991-06-25 | 1992-06-24 | | 10001 | 74333 | 1992-06-24 | 1993-06-24 | | 10001 | 75286 | 1993-06-24 | 1994-06-24 | | 10001 | 75994 | 1994-06-24 | 1995-06-24 | | 10001 | 76884 | 1995-06-24 | 1996-06-23 | +--------+--------+------------+------------+
【関連記事】
▶SQLで重複を削除するサンプルコード 最新データを残してdeleteするには?
まとめ
- 特定のデータを除くには、not inを使う。
- 単純な重複を除くにはdistinct 指定が便利。
- サブクエリを組み合わせると、動的なデータに対して「除く」指定が可能。