サーチ…
前書き
SELECTステートメントは、ほとんどのSQL照会の中心です。どの結果セットがクエリによって返されるべきかを定義し、ほとんどの場合、データベースのどの部分を照会するかを定義するFROM句とともに使用されます。
構文
SELECT [DISTINCT] [column1] [、[column2] ...]
FROM [table]
[WHERE条件]
[GROUP BY [列1] [、[列2] ...][HAVING [列1] [、[列2] ...]
[オーダーby ASC | DESC]
備考
SELECTは 、特定のテーブルから返すカラムのデータと、そのカラムの順番を決定します。
SELECT Name, SerialNumber
FROM ArmyInfo
Name
とSerial Number
列の結果のみを返しますが、 Rank
という列の結果は返しません。
SELECT *
FROM ArmyInfo
すべての列が返されることを示します。ただし、実際にはテーブルのすべての列を返すので、 SELECT *
を実行することは貧弱です。
ワイルドカード文字を使用して、クエリのすべての列を選択します。
次の2つのテーブルを持つデータベースを考えてみましょう。
従業員テーブル:
イド | FName | LName | DeptId |
---|---|---|---|
1 | ジェームス | スミス | 3 |
2 | ジョン | ジョンソン | 4 |
部署テーブル:
イド | 名 |
---|---|
1 | 販売 |
2 | マーケティング |
3 | ファイナンス |
4 | それ |
単純なselectステートメント
*
は、テーブル内の使用可能なすべての列を選択するために使用されるワイルドカード文字です。
明示的な列名の代用として使用すると、クエリがFROM
選択しているすべての表のすべての列がFROM
ます。このエフェクトは、クエリがJOIN
句を使用してアクセスするすべてのテーブルに適用されます。
以下のクエリを考えてみましょう。
SELECT * FROM Employees
Employees
テーブルのすべての行のすべてのフィールドが返されます。
イド | FName | LName | DeptId |
---|---|---|---|
1 | ジェームス | スミス | 3 |
2 | ジョン | ジョンソン | 4 |
ドット表記
特定のテーブルからすべての値を選択するには、ワイルドカード文字をドット表記でテーブルに適用できます。
以下のクエリを考えてみましょう。
SELECT
Employees.*,
Departments.Name
FROM
Employees
JOIN
Departments
ON Departments.Id = Employees.DeptId
これにより、 Employee
テーブルのすべてのフィールドを含むデータセットが返され、その後にDepartments
テーブルのName
フィールドだけが返されます。
イド | FName | LName | DeptId | 名 |
---|---|---|---|---|
1 | ジェームス | スミス | 3 | ファイナンス |
2 | ジョン | ジョンソン | 4 | それ |
使用上の警告
可能であれば、プロダクションコードで*
を使用することは回避されることが一般的に推奨されています。
- データベースエンジンが不要なデータを読み込んでフロントエンドコードに送信するため、IO、ネットワーク負荷、メモリ使用量が過剰です。これは、長い音符や添付ファイルを格納するのに使用されるような大きなフィールドが存在する場合に特に重要です。
-
SELECT <columns> FROM <table>
よりも複雑なクエリの処理の一部として、データベースが内部結果をディスクにスプールする必要がある場合は、さらに過剰なIO負荷が発生します。 - 不要な列の一部が次のような場合は、余分な処理(および/またはさらにIO)が発生します。
- それらをサポートするデータベースの計算カラム
- ビューから選択する場合、クエリオプティマイザが他の方法で最適化できるテーブル/ビューの列
- テーブルやビューに後で追加された列があいまいな列名になった場合、予期しないエラーが発生する可能性があります。たとえば、
SELECT * FROM orders JOIN people ON people.id = orders.personid ORDER BY displayname
という列欄場合-displayname
、ユーザーが自分の注文今後の参考のために意味のある名前を付けることができるように受注テーブルに追加された後、列名が表示されますORDER BY
句があいまいでエラーを引き起こす可能性があるため(最近のMS SQL Serverバージョンではあいまいな列名)、この例ではない場合、アプリケーション名に人名が表示される注文コードが表示されることがあります新しい列が返された最初の名前であるなどのために意図されています。
あなたは*
使用することができますか?警告を警告していますか?
プロダクションコードでは避けるのが最善ですが、調査やプロトタイプ作業のためにデータベースに対して手動クエリーを実行する場合は、 *
を使用するのが簡略です。
時々 、(このような状況では、好むそれはやむを得ない作るアプリケーションでの意思決定を設計tablealias.*
わずか*
可能な場合)。
SELECT A.col1, A.Col2 FROM A WHERE EXISTS (SELECT * FROM B where A.ID = B.A_ID)
などのEXISTS
を使用する場合、Bからのデータは返されません。したがって、結合は不要で、エンジンはBからの値が返されないことを知っているので、 *
を使用したときのパフォーマンスは低下しません。同様に、 COUNT(*)
は実際には列を返さないため、フィルタリング目的で使用されるものを読み込んで処理するだけで済みます。
条件で選択する
SELECT WHERE句の基本構文は次のとおりです。
SELECT column1, column2, columnN
FROM table_name
WHERE [condition]
[condition]には、>、<、=、<>、> =、<=、LIKE、NOT、IN、BETWEENなどの比較演算子または論理演算子を使用して指定した任意のSQL式を指定できます。
次の文は、ステータス列が 'READY'の 'Cars'テーブルからすべての列を返します。
SELECT * FROM Cars WHERE status = 'READY'
より多くの例については、 WHEREとHAVINGを参照してください。
個々の列を選択
SELECT
PhoneNumber,
Email,
PreferredContact
FROM Customers
このステートメントは、 Customers
テーブルのすべての行からPhoneNumber
、 Email
、およびPreferredContact
という列を返します。また、列はSELECT
節に現れる順序で戻されます。
結果は次のようになります。
電話番号 | Eメール | PreferredContact |
---|---|---|
3347927472 | [email protected] | 電話 |
2137921892 | [email protected] | Eメール |
ヌル | [email protected] | Eメール |
複数の表が結合されている場合、列名の前に表名を指定することにより、特定の表から列を選択できます[table_name].[column_name]
SELECT
Customers.PhoneNumber,
Customers.Email,
Customers.PreferredContact,
Orders.Id AS OrderId
FROM
Customers
LEFT JOIN
Orders ON Orders.CustomerId = Customers.Id
* AS OrderId
は、 Orders
テーブルのId
フィールドがOrderId
という名前の列として返されることをOrderId
ます。詳細については、列エイリアスの選択を参照してください。
長いテーブル名を使用しないようにするには、テーブルエイリアスを使用できます。これにより、ジョインで選択した各フィールドの長いテーブル名を書き込む苦労が軽減されます。自己結合( 同じ表の2つのインスタンス間の結合)を実行する場合は、表の別名を使用して表を区別する必要があります。 Customers c
やCustomers AS c
ようなテーブルエイリアスを書くことができます。ここでc
はCustomers
エイリアスとして動作し、次のようなEmail
選択します: c.Email
。
SELECT
c.PhoneNumber,
c.Email,
c.PreferredContact,
o.Id AS OrderId
FROM
Customers c
LEFT JOIN
Orders o ON o.CustomerId = c.Id
列エイリアスを使用したSELECT
列エイリアスは主にコードを短縮し、列名をより読みやすくするために使用されます。
テーブル名が長く、不要な列の識別(たとえば、テーブルに2つのIDがありますが、1つだけが使用されている)ほど、コードは短くなります。 テーブルのエイリアスに加えて、これにより、データベース構造でよりわかりやすい名前を使用して、その構造を簡潔に照会することができます。
さらに、計算された出力に名前を付けるために、ビューなどで必要になることがあります。
すべてのバージョンのSQL
エイリアスは、すべてのバージョンのSQLで二重引用符( "
)を使用して作成できます。
SELECT
FName AS "First Name",
MName AS "Middle Name",
LName AS "Last Name"
FROM Employees
異なるバージョンのSQL
Microsoft SQL Serverでエイリアスを作成するには、一重引用符( '
)、二重引用符( "
)、角括弧( []
)を使用できます。
SELECT
FName AS "First Name",
MName AS 'Middle Name',
LName AS [Last Name]
FROM Employees
どちらも結果になります:
ファーストネーム | ミドルネーム | 苗字 |
---|---|---|
ジェームス | ジョン | スミス |
ジョン | ジェームス | ジョンソン |
マイケル | マーカス | ウィリアムズ |
この文は、返されFName
とLName
与えられた名前(別名)の列を。これは、エイリアスが後に続くAS
演算子を使用するか、単に列名の後ろにエイリアスを書き込むことで実現されます。つまり、次のクエリは上記と同じ結果になります。
SELECT
FName "First Name",
MName "Middle Name",
LName "Last Name"
FROM Employees
ファーストネーム | ミドルネーム | 苗字 |
---|---|---|
ジェームス | ジョン | スミス |
ジョン | ジェームス | ジョンソン |
マイケル | マーカス | ウィリアムズ |
しかし、明示的なバージョン(つまり、 AS
演算子を使用する)は、より読みやすくなります。
エイリアスに予約語ではない単一の単語がある場合は、一重引用符、二重引用符、または大括弧なしで記述できます。
SELECT
FName AS FirstName,
LName AS LastName
FROM Employees
ファーストネーム | 苗字 |
---|---|
ジェームス | スミス |
ジョン | ジョンソン |
マイケル | ウィリアムズ |
とりわけ、MS SQL Serverで利用可能な別のバリエーションは<alias> = <column-or-calculation>
です。たとえば、次のようになります。
SELECT FullName = FirstName + ' ' + LastName,
Addr1 = FullStreetAddress,
Addr2 = TownName
FROM CustomerDetails
これは以下と同等です:
SELECT FirstName + ' ' + LastName As FullName
FullStreetAddress As Addr1,
TownName As Addr2
FROM CustomerDetails
どちらも結果になります:
フルネーム | Addr1 | Addr2 |
---|---|---|
ジェームズスミス | 123 AnyStreet | TownVille |
ジョンジョンソン | 668 MyRoad | Anytown |
マイケル・ウィリアムズ | 999ハイ・エンド・ドクター | ウィリアムズバーグ |
いくつかは、使用して見つける=
の代わりにAs
多くは、それが標準ではない主な理由はとても広く、すべてのデータベースでサポートされていない、このフォーマットに対してお勧めしますが、読みやすいです。 =
文字を他の用途と混同する可能性があります。
すべてのSQLバージョン
また、予約語を使用する必要がある場合は、大括弧または引用符を使用してエスケープすることもできます。
SELECT
FName as "SELECT",
MName as "FROM",
LName as "WHERE"
FROM Employees
異なるバージョンのSQL
同様に、MSSQLでキーワードをエスケープするには、さまざまな方法があります。
SELECT
FName AS "SELECT",
MName AS 'FROM',
LName AS [WHERE]
FROM Employees
セレクト | から | どこに |
---|---|---|
ジェームス | ジョン | スミス |
ジョン | ジェームス | ジョンソン |
マイケル | マーカス | ウィリアムズ |
また、列エイリアスは、 ORDER BY
などの同じクエリの最終節のいずれかに使用できます。
SELECT
FName AS FirstName,
LName AS LastName
FROM
Employees
ORDER BY
LastName DESC
ただし、使用することはできません
SELECT
FName AS SELECT,
LName AS FROM
FROM
Employees
ORDER BY
LastName DESC
これらの予約語( SELECT
およびFROM
)からエイリアスを作成するには
これにより、実行時に多数のエラーが発生します。
ソートされた結果を含む選択
SELECT * FROM Employees ORDER BY LName
このステートメントは、 Employees
テーブルからすべての列を返します。
イド | FName | LName | 電話番号 |
---|---|---|---|
2 | ジョン | ジョンソン | 2468101214 |
1 | ジェームス | スミス | 1234567890 |
3 | マイケル | ウィリアムズ | 1357911131 |
SELECT * FROM Employees ORDER BY LName DESC
または
SELECT * FROM Employees ORDER BY LName ASC
この文はソート方向を変更します。
複数のソート列を指定することもできます。例えば:
SELECT * FROM Employees ORDER BY LName ASC, FName ASC
この例では、まずLName
結果をソートし、同じLName
を持つレコードについてはLName
でソートしFName
。これにより、電話帳での検索結果と同様の結果が得られます。
ORDER BY
句に列名を再入力するのを保存するために、代わりに列の番号を使用することができます。列番号は1から始まることに注意してください。
SELECT Id, FName, LName, PhoneNumber FROM Employees ORDER BY 3
ORDER BY
句にCASE
文を埋め込むこともできます。
SELECT Id, FName, LName, PhoneNumber FROM Employees ORDER BY CASE WHEN LName='Jones` THEN 0 ELSE 1 END ASC
これにより結果がソートされ、 "Jones"のLName
を持つすべてのレコードが一番上に表示されます。
予約されたキーワードの後に名前が付けられた列を選択する
列名が予約されたキーワードと一致する場合、標準SQLでは二重引用符で囲む必要があります。
SELECT
"ORDER",
ID
FROM ORDERS
カラム名は大文字と小文字を区別します。
DBMSによっては、名前を引用する独自の方法があります。たとえば、SQL Serverはこの目的に角括弧を使用します。
SELECT
[Order],
ID
FROM ORDERS
MySQL(とMariaDB)はデフォルトでバッククォートを使います:
SELECT
`Order`,
id
FROM orders
指定したレコード数を選択する
SQL 2008標準では、返されるレコード数を制限するためにFETCH FIRST
句が定義されています 。
SELECT Id, ProductName, UnitPrice, Package
FROM Product
ORDER BY UnitPrice DESC
FETCH FIRST 10 ROWS ONLY
この規格は、最近のバージョンのRDMSでのみサポートされています。ベンダー固有の非標準構文が他のシステムで提供されています。進捗OpenEdge 11.xはFETCH FIRST <n> ROWS ONLY
構文もサポートしています。
さらに、 FETCH FIRST <n> ROWS ONLY
前にOFFSET <m> ROWS
すると、行をフェッチする前に行をスキップすることができます。
SELECT Id, ProductName, UnitPrice, Package
FROM Product
ORDER BY UnitPrice DESC
OFFSET 5 ROWS
FETCH FIRST 10 ROWS ONLY
SQL ServerとMS Accessで次のクエリがサポートされています 。
SELECT TOP 10 Id, ProductName, UnitPrice, Package
FROM Product
ORDER BY UnitPrice DESC
MySQLまたはPostgreSQLで同じことを行うには、 LIMIT
キーワードを使用する必要があります。
SELECT Id, ProductName, UnitPrice, Package
FROM Product
ORDER BY UnitPrice DESC
LIMIT 10
OracleではROWNUM
でも同じことができます:
SELECT Id, ProductName, UnitPrice, Package
FROM Product
WHERE ROWNUM <= 10
ORDER BY UnitPrice DESC
結果 : 10レコード。
Id ProductName UnitPrice Package
38 Côte de Blaye 263.50 12 - 75 cl bottles
29 Thüringer Rostbratwurst 123.79 50 bags x 30 sausgs.
9 Mishi Kobe Niku 97.00 18 - 500 g pkgs.
20 Sir Rodney's Marmalade 81.00 30 gift boxes
18 Carnarvon Tigers 62.50 16 kg pkg.
59 Raclette Courdavault 55.00 5 kg pkg.
51 Manjimup Dried Apples 53.00 50 - 300 g pkgs.
62 Tarte au sucre 49.30 48 pies
43 Ipoh Coffee 46.00 16 - 500 g tins
28 Rössle Sauerkraut 45.60 25 - 825 g cans
ベンダーニュアンス:
Microsoft SQLのTOP
はWHERE
句の後に動作し、テーブルのどこにでも存在する場合は指定された数の結果を返すことに注意してROWNUM
はWHERE
句の一部として機能します。テーブルの先頭に指定された行数を指定すると、見つかる可能性がある場合はゼロの結果が得られます。
テーブルエイリアスで選択する
SELECT e.Fname, e.LName
FROM Employees e
Employeesテーブルには、テーブル名の直後に別名「e」が付けられます。これにより、複数のテーブルが同じフィールド名を持ち、データを返すテーブルを特定する必要がある場合に、あいまいさを取り除くのに役立ちます。
SELECT e.Fname, e.LName, m.Fname AS ManagerFirstName
FROM Employees e
JOIN Managers m ON e.ManagerId = m.Id
エイリアスを定義すると、正規テーブル名を使用できなくなります。すなわち、
SELECT e.Fname, Employees.LName, m.Fname AS ManagerFirstName
FROM Employees e
JOIN Managers m ON e.ManagerId = m.Id
エラーが発生します。
INNER JOIN
によって引き起こされた重複列の問題を解決するために、より正式には「範囲変数」という表のエイリアスがSQL言語に導入されました。 1992年のSQL標準では、 NATURAL JOIN
(mySQL、PostgreSQL、Oracleでは実装されていますがSQL Serverでは実装されていません)を導入することにより、この初期の設計上の欠陥を修正しました。上記の例は、テーブルが異なる名前( Id
およびManagerId
)を持つ列で結合されているが、同じ名前( LName
、 FName
)の列に結合されていないため、実行する列の名前を変更する必要がある参加前 :
SELECT Fname, LName, ManagerFirstName
FROM Employees
NATURAL JOIN
( SELECT Id AS ManagerId, Fname AS ManagerFirstName
FROM Managers ) m;
derviedテーブルに対してエイリアス/範囲変数を宣言しなければなりませんが(そうでないとSQLはエラーを投げます)、クエリで実際に使用することは決してできません。
複数の表から行を選択する
SELECT *
FROM
table1,
table2
SELECT
table1.column1,
table1.column2,
table2.column1
FROM
table1,
table2
これはSQLのクロスプロダクトと呼ばれ、セット内のクロスプロダクトと同じです
これらのステートメントは、1つのクエリで複数のテーブルから選択した列を返します。
各表から戻される列には特定の関係はありません。
集計関数による選択
平均
AVG()
集計関数は、選択された値の平均を返します。 SELECT AVG(Salary) FROM Employees
集約関数をwhere句と組み合わせることもできます。 SELECT AVG(Salary) FROM Employees where DepartmentId = 1
集合関数はgroup by節と組み合わせることもできます。 従業員が複数の部門に分類され、部門ごとに平均給与を求めたい場合は、次のクエリを使用できます。
SELECT AVG(Salary) FROM Employees GROUP BY DepartmentId
最小
MIN()
集計関数は、選択された最小値を返します。 SELECT MIN(Salary) FROM Employees
最大
MAX()
集合関数は選択された最大値を返します。 SELECT MAX(Salary) FROM Employees
カウント
COUNT()
集計関数は、選択された値の数を返します。 SELECT Count(*) FROM Employees
特定の条件を満たす行の数を取得する条件と組み合わせることもできます。 SELECT Count(*) FROM Employees where ManagerId IS NOT NULL
特定の列を指定して、列内の値の数を取得することもできます。 NULL
値はカウントされないことに注意してください。 Select Count(ManagerId) from Employees
Countはdistinct countとdistinctキーワードで組み合わせることもできます。 Select Count(DISTINCT DepartmentId) from Employees
和
SUM()
集計関数は、すべての行に対して選択された値の合計を返します。 SELECT SUM(Salary) FROM Employees
ヌルで選択する
SELECT Name FROM Customers WHERE PhoneNumber IS NULL
NULLを使用した選択は、異なる構文をとります。 =
を使用しないでください。代わりにIS NULL
またはIS NOT NULL
使用してください。
CASEで選択する
結果にあるロジックを 'オンザフライで'適用する必要がある場合、CASE文を使用してそれを実装できます。
SELECT CASE WHEN Col1 < 50 THEN 'under' ELSE 'over' END threshold
FROM TableName
また、チェーン接続することもできます
SELECT
CASE WHEN Col1 < 50 THEN 'under'
WHEN Col1 > 50 AND Col1 <100 THEN 'between'
ELSE 'over'
END threshold
FROM TableName
CASE
を別のCASE
文の中に入れることもできます
SELECT
CASE WHEN Col1 < 50 THEN 'under'
ELSE
CASE WHEN Col1 > 50 AND Col1 <100 THEN Col1
ELSE 'over' END
END threshold
FROM TableName
テーブルをロックせずに選択する
時々テーブルが読み込みのために大部分(または唯一の)使用されるとき、索引付けはもはや助けにはならず、小さなビットがカウントされると、パフォーマンスを改善するためにLOCKのないselectを使用することがあります。
SQLサーバー
SELECT * FROM TableName WITH (nolock)
MySQL
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM TableName;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
オラクル
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM TableName;
DB2
SELECT * FROM TableName WITH UR;
ここで、 UR
は「コミットされていない読み取り」を表します。
レコードの修正が行われているテーブルで使用すると、予期しない結果が生じる可能性があります。
個別(一意の値のみ)を選択
SELECT DISTINCT ContinentCode
FROM Countries;
このクエリは、 Countries
テーブルのContinentCode
列からすべてのDISTINCT
(固有の異なる値)を返します
ContinentCode |
---|
OC |
EU |
として |
NA |
AF |
列から複数の値の条件で選択
SELECT * FROM Cars WHERE status IN ( 'Waiting', 'Working' )
これは意味的に
SELECT * FROM Cars WHERE ( status = 'Waiting' OR status = 'Working' )
すなわち、 value IN ( <value list> )
は論理和(論理OR
)の略語です。
行グループの集計結果を得る
特定の列の値に基づいて行を数える:
SELECT category, COUNT(*) AS item_count
FROM item
GROUP BY category;
部門別平均所得の取得:
SELECT department, AVG(income)
FROM employees
GROUP BY department;
重要なのは、 GROUP BY
句で指定された列のみを選択するか、 集約関数で使用する列だけを選択することです。
そこWHERE
句はしても使用することができGROUP BY
が、 WHERE
任意のグループ化が行われる前にレコードをフィルタリングします。
SELECT department, AVG(income)
FROM employees
WHERE department <> 'ACCOUNTING'
GROUP BY department;
たとえば、平均収入が1000を超える部門のみを表示するなど、グループ化が完了した後に結果をフィルタリングする必要がある場合は、 HAVING
句を使用する必要があります。
SELECT department, AVG(income)
FROM employees
WHERE department <> 'ACCOUNTING'
GROUP BY department
HAVING avg(income) > 1000;
複数の条件で選択する。
AND
キーワードは、クエリに条件を追加するために使用されます。
名 | 年齢 | 性別 |
---|---|---|
サム | 18 | M |
ジョン | 21 | M |
ボブ | 22 | M |
メアリー | 23 | F |
SELECT name FROM persons WHERE gender = 'M' AND age > 20;
これは返されます:
名 |
---|
ジョン |
ボブ |
OR
キーワードを使用して
SELECT name FROM persons WHERE gender = 'M' OR age < 20;
これは返されます:
名 |
---|
サム |
ジョン |
ボブ |
これらのキーワードを組み合わせると、より複雑な条件の組み合わせが可能になります。
SELECT name
FROM persons
WHERE (gender = 'M' AND age < 20)
OR (gender = 'F' AND age > 20);
これは返されます:
名 |
---|
サム |
メアリー |