SELECT DISTINCTとGROUP BYの組み合わせによる重複排除
SQL Server で特定の列のみを DISTINCT する方法
SELECT DISTINCT と GROUP BY の組み合わせ
特定の列のみを DISTINCT にするには、SELECT DISTINCT と GROUP BY を組み合わせて使用します。
SELECT DISTINCT 列名
FROM テーブル名
GROUP BY 列名;
例:
SELECT DISTINCT 国籍
FROM 顧客;
この例では、顧客 テーブルから 国籍 列の重複を除外して、各国の顧客を1行ずつ表示します。
GROUP BY と集計関数 (COUNT、SUM、AVG など) を組み合わせることで、特定の列の重複を除外しながら、集計結果を表示することもできます。
SELECT 列名, COUNT(*) AS 件数
FROM テーブル名
GROUP BY 列名;
SELECT 国籍, COUNT(*) AS 件数
FROM 顧客
GROUP BY 国籍;
この例では、顧客 テーブルの 国籍 列ごとに顧客数を集計し、重複を除外して表示します。
サブクエリを使用して、DISTINCT 処理を行うこともできます。
SELECT *
FROM (
SELECT DISTINCT 列名
FROM テーブル名
) AS サブクエリ;
SELECT *
FROM (
SELECT DISTINCT 国籍
FROM 顧客
) AS サブクエリ;
この例では、顧客 テーブルの 国籍 列の重複を除外した結果をサブクエリとして格納し、そのサブクエリを元にすべての列を表示します。
窓関数
SQL Server 2005 以降では、ROW_NUMBER() などの窓関数を使用して、特定の列のみを DISTINCT にすることができます。
SELECT 列名, ROW_NUMBER() OVER (PARTITION BY 列名 ORDER BY 列名) AS 行番号
FROM テーブル名;
SELECT 国籍, ROW_NUMBER() OVER (PARTITION BY 国籍 ORDER BY 国籍) AS 行番号
FROM 顧客;
この例では、顧客 テーブルの 国籍 列ごとにROW_NUMBER() 関数を用いて行番号を付与し、重複する行番号を除外して表示します。
注意点
- DISTINCT は、インデックスを使用できない場合があります。
- DISTINCT は、パフォーマンスに影響を与える可能性があります。
- DISTINCT は、NULL 値を考慮しません。
上記の方法を参考に、状況に合わせて適切な方法を選択してください。
-- テーブル作成
CREATE TABLE 顧客 (
顧客ID INT,
氏名 VARCHAR(50),
国籍 VARCHAR(50),
年齢 INT
);
-- データ挿入
INSERT INTO 顧客 VALUES (1, '山田太郎', '日本', 20);
INSERT INTO 顧客 VALUES (2, '田中花子', '日本', 21);
INSERT INTO 顧客 VALUES (3, '佐藤一郎', 'アメリカ', 22);
INSERT INTO 顧客 VALUES (4, '斎藤美咲', 'アメリカ', 22);
-- SELECT DISTINCT
SELECT DISTINCT 国籍
FROM 顧客;
結果:
日本
アメリカ
GROUP BY と集計関数の組み合わせ
SELECT 国籍, COUNT(*) AS 件数
FROM 顧客
GROUP BY 国籍;
国籍 件数
日本 2
アメリカ 2
サブクエリ
SELECT *
FROM (
SELECT DISTINCT 国籍
FROM 顧客
) AS サブクエリ;
国籍
日本
アメリカ
SELECT 国籍, ROW_NUMBER() OVER (PARTITION BY 国籍 ORDER BY 国籍) AS 行番号
FROM 顧客;
国籍 行番号
日本 1
日本 2
アメリカ 1
アメリカ 2
SELECT DISTINCT 国籍, 氏名
FROM 顧客
ORDER BY 国籍, 氏名;
国籍 氏名
日本 山田太郎
日本 田中花子
アメリカ 斎藤美咲
アメリカ 佐藤一郎
SELECT DISTINCT 国籍, 氏名
FROM 顧客
ORDER BY 国籍
TOP 1;
国籍 氏名
アメリカ 斎藤美咲
SELECT *
FROM 顧客
WHERE EXISTS (
SELECT *
FROM 顧客 AS サブクエリ
WHERE サブクエリ.国籍 = 顧客.国籍
AND サブクエリ.年齢 > 20
);
顧客ID 氏名 国籍 年齢
2 田中花子 日本 21
4 斎藤美咲 アメリカ 22
SELECT *
FROM 顧客
WHERE 国籍 NOT IN ('日本');
顧客ID 氏名 国籍 年齢
3 佐藤一郎 アメリカ 22
4 斎藤美咲 アメリカ 22
SELECT DISTINCT
CASE
WHEN 国籍 = '日本' THEN '日本人'
ELSE '外国人'
END AS 国籍区分
FROM 顧客;
国籍区分
日本人
外国人
SELECT DISTINCT 国籍
FROM 顧客
WHERE 国籍 LIKE '%ア%';
国籍
アメリカ
SELECT 国籍, COUNT(*) AS 件数
FROM 顧客
GROUP BY 国籍
HAVING COUNT(*) > 1;
国籍 件数
日本 2
SQL Server で特定の列のみを DISTINCT する方法:その他の方法
CTE (Common Table Expression)
CTE を使用することで、複雑なクエリをより読みやすく、理解しやすいコードに分割することができます。
WITH 顧客_国籍 AS (
SELECT DISTINCT 国籍
FROM 顧客
)
SELECT *
FROM 顧客_国籍;
UNION ALL を使用することで、重複する行をすべて含む結果セットを作成できます。
SELECT DISTINCT 国籍
FROM 顧客
UNION ALL
SELECT DISTINCT 国籍
FROM 顧客 AS サブクエリ
WHERE サブクエリ.年齢 > 20;
EXCEPT を使用することで、2 つの結果セットから重複する行を除外することができます。
SELECT DISTINCT 国籍
FROM 顧客
EXCEPT
SELECT DISTINCT 国籍
FROM 顧客 AS サブクエリ
WHERE サブクエリ.国籍 = '日本';
SELECT DISTINCT 国籍
FROM 顧客
INTERSECT
SELECT DISTINCT 国籍
FROM 顧客 AS サブクエリ
WHERE サブクエリ.年齢 > 20;
SCALAR SUBQUERY を使用することで、サブクエリの結果を単一の値として返すことができます。
SELECT 氏名
FROM 顧客
WHERE 国籍 IN (
SELECT DISTINCT 国籍
FROM 顧客
);
CROSS APPLY を使用することで、テーブル間の行を結合することができます。
SELECT 顧客.氏名, サブクエリ.国籍
FROM 顧客
CROSS APPLY (
SELECT DISTINCT 国籍
FROM 顧客 AS サブクエリ
WHERE サブクエリ.年齢 > 20
) AS サブクエリ;
SELECT 顧客.氏名, サブクエリ.国籍
FROM 顧客
OUTER APPLY (
SELECT DISTINCT 国籍
FROM 顧客 AS サブクエリ
WHERE サブクエリ.年齢 > 20
) AS サブクエリ;
PIVOT を使用することで、列を値として、行をキーとして集計することができます。
SELECT 国籍, SUM(年齢) AS 合計年齢
FROM 顧客
PIVOT (
SUM(年齢)
FOR 国籍 IN ('日本', 'アメリカ')
) AS サブクエリ;
SELECT 国籍, 年齢
FROM 顧客
UNPIVOT (
年齢
FOR 国籍 IN ('日本', 'アメリカ')
) AS サブクエリ;
FOR XML PATH を使用することで、XML 形式で結果セットを返すことができます。
SELECT *
FROM 顧客
FOR XML PATH('');
sql sql-server