サーチ…


前書き

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

NameSerial 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 それ

使用上の警告

可能であれば、プロダクションコードで*を使用することは回避されることが一般的に推奨されています。

  1. データベースエンジンが不要なデータを読み込んでフロントエンドコードに送信するため、IO、ネットワーク負荷、メモリ使用量が過剰です。これは、長い音符や添付ファイルを格納するのに使用されるような大きなフィールドが存在する場合に特に重要です。
  2. SELECT <columns> FROM <table>よりも複雑なクエリの処理の一部として、データベースが内部結果をディスクにスプールする必要がある場合は、さらに過剰なIO負荷が発生します。
  3. 不要な列の一部が次のような場合は、余分な処理(および/またはさらにIO)が発生します。
    • それらをサポートするデータベースの計算カラム
    • ビューから選択する場合、クエリオプティマイザが他の方法で最適化できるテーブル/ビューの列
  4. テーブルやビューに後で追加された列があいまいな列名になった場合、予期しないエラーが発生する可能性があります。たとえば、 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テーブルのすべての行からPhoneNumberEmail 、および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 cCustomers AS cようなテーブルエイリアスを書くことができます。ここでcCustomersエイリアスとして動作し、次のような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  

どちらも結果になります:

ファーストネームミドルネーム苗字
ジェームスジョンスミス
ジョンジェームスジョンソン
マイケルマーカスウィリアムズ

この文は、返されFNameLName与えられた名前(別名)の列を。これは、エイリアスが後に続く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のTOPWHERE句の後に動作し、テーブルのどこにでも存在する場合は指定された数の結果を返すことに注意してROWNUMWHERE句の一部として機能します。テーブルの先頭に指定された行数を指定すると、見つかる可能性がある場合はゼロの結果が得られます。

テーブルエイリアスで選択する

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 )を持つ列で結合されているが、同じ名前( LNameFName )の列に結合されていないため、実行する列の名前を変更する必要がある参加

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

SQLFiddleデモ

列から複数の値の条件で選択

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);

これは返されます:

サム
メアリー


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow