次の方法で共有


SELECT - ORDER BY 句 (Transact-SQL)

Applies to: SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW) Microsoft Fabric の SQL 分析エンドポイント Microsoft Fabric のウェアハウス

SQL Server でクエリによって返されるデータを並べ替えます。 この句は次の場合に使用します。

  • 指定した列リストでクエリの結果セットを並べ替え、必要に応じて、返される行を指定の範囲に制限する。 ORDER BY句が指定されていない限り、結果セットで行が返される順序は保証されません。

  • 順位付け関数の値が結果セットに適用される順序を決定する。

Transact-SQL 構文表記規則

Note

ORDER BY は、Azure Synapse Analytics または Analytics Platform System (PDW) の SELECT/INTO または CREATE TABLE AS SELECT (CTAS) ステートメントではサポートされていません。

構文

SQL Server および Azure SQL データベース の構文

ORDER BY order_by_expression
    [ COLLATE collation_name ]
    [ ASC | DESC ]
    [ , ...n ]
[ <offset_fetch> ]

<offset_fetch> ::=
{
    OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
    [
      FETCH { FIRST | NEXT } { integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY
    ]
}

Azure Synapse Analytics と Parallel Data Warehouse の構文。

[ ORDER BY
    {
    order_by_expression
    [ ASC | DESC ]
    } [ , ...n ]
]

引数

order_by_expression

クエリの結果セットの並べ替えに使用する列または式を指定します。 並べ替え列は、名前または列の別名、または選択リスト内の列の位置を表す負でない整数として指定できます。

並べ替え列は複数指定できます。 列名は一意である必要があります。 ORDER BY句の並べ替え列のシーケンスによって、並べ替えられた結果セットの編成が定義されます。 つまり、結果セットが最初の列を基準に並べ替えられた後、その並べ替えられたリストが 2 つ目の列を基準に並べ替えられます。それ以降も同様の並べ替えが行われます。

ORDER BY句で参照される列名は、選択リストの列または列の別名、またはFROM句で指定されたテーブルで定義されている列に対応する必要があります。あいまいさはありません。 ORDER BY句が選択リストから列の別名を参照する場合、列の別名は、ORDER BY句の式の一部としてではなく、単独で使用する必要があります。次に例を示します。

SELECT SCHEMA_NAME(schema_id) AS SchemaName
FROM sys.objects
ORDER BY SchemaName; -- correct

SELECT SCHEMA_NAME(schema_id) AS SchemaName
FROM sys.objects
ORDER BY SchemaName + ''; -- wrong

COLLATE collation_name

テーブルまたはビューで定義されている列の照合順序に従ってではなく、collation_nameで指定された照合順序に従って、ORDER BY操作を実行するように指定します。 collation_nameには、Windows 照合順序名または SQL 照合順序名を指定できます。 詳細については、「照合順序および Unicode のサポート」を参照してください。 COLLATE は、 charvarcharnchar、および nvarchar の列にのみ適用されます。

ASC | DESC

指定した列の値を昇順と降順のどちらで並べ替えるかを指定します。 ASC を指定した場合、最小値から最大値の順序で並べ替えられます。 DESC を指定した場合、最大値から最小値の順序で並べ替えられます。 ASC が既定の並べ替え順序です。 NULL 値は最小値として扱われます。

OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }

適用対象: SQL Server 2012 (11.x) 以降のバージョン、Azure SQL Database、および Azure SQL Managed Instance。

クエリ式から行を取得する前にスキップする行の数を指定します。 0 以上の整数の定数か式を指定できます。

offset_row_count_expression には、変数、パラメーター、または定数スカラー サブクエリを指定できます。 サブクエリを使用する場合、外部クエリ スコープで定義されている列を参照することはできません。 つまり、外部クエリと関連付けることはできません。

ROW および ROWS はシノニムであり、ANSI 互換性のために提供されます。

クエリ実行プランでは、オフセット行数の値は、TOP クエリ演算子の Offset 属性に表示されます。

FETCH { FIRST | NEXT } { integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY

適用対象: SQL Server 2012 (11.x) 以降のバージョン、Azure SQL Database、および Azure SQL Managed Instance。

OFFSET句の処理後に返す行数を指定します。 1 以上の整数の定数か式を指定できます。

fetch_row_count_expression には、変数、パラメーター、または定数スカラー サブクエリを指定できます。 サブクエリを使用する場合、外部クエリ スコープで定義されている列を参照することはできません。 つまり、外部クエリと関連付けることはできません。

FIRST および NEXT はシノニムであり、ANSI 互換性のために提供されます。

ROW および ROWS はシノニムであり、ANSI 互換性のために提供されます。

クエリ実行プランでは、オフセット行数の値は、TOP クエリ演算子の Rows または Top 属性に表示されます。

ベスト プラクティス

ORDER BY句では、選択リスト内の列の位置指定として整数を指定しないでください。 たとえば、 SELECT ProductID, Name FROM Production.Production ORDER BY 2 などのステートメントは有効ですが、実際の列名を指定する場合と比較して、他のユーザーがステートメントを簡単に理解することはできません。 さらに、列の順序の変更や新しい列の追加など、選択リストを変更するには、予期しない結果を回避するために ORDER BY 句を変更する必要があります。

SELECT TOP (<n>) ステートメントでは、常に ORDER BY 句を使用します。 これは、 TOPの影響を受ける行を予測可能に示す唯一の方法です。 詳細については、「TOP」を参照してください。

相互運用性

SELECT...INTOまたはINSERT...SELECTステートメントと共に使用して別のソースから行を挿入する場合、ORDER BY句では、指定した順序で行が挿入されるとは限りません。

ビューで OFFSETFETCH を使用しても、ビューの更新可能性プロパティは変更されません。

制限事項

ORDER BY句の列数に制限はありません。 ただし、 ORDER BY 句で指定された列の合計サイズは 8,060 バイトを超えることはできません。

ntexttextimagegeographygeometry、および xml の列は、ORDER BY句では使用できません。

ランク付け関数に order_by_expression が表示される場合は、整数または定数を指定できません。 詳細については、 SELECT - OVER 句を参照してください。

テーブル名が FROM 句でエイリアス化されている場合は、エイリアス名のみを使用して、 ORDER BY 句の列を修飾できます。

SELECT ステートメントに次のいずれかの句または演算子が含まれている場合は、ORDER BY句で指定された列名とエイリアスを選択リストで定義する必要があります。

  • UNION 演算子
  • EXCEPT 演算子
  • INTERSECT 演算子
  • SELECT DISTINCT

さらに、ステートメントに UNIONEXCEPT、または INTERSECT 演算子が含まれている場合は、最初の (左側) クエリの選択リストで列名または列の別名を指定する必要があります。

UNIONEXCEPT、またはINTERSECT演算子を使用するクエリでは、ORDER BYはステートメントの末尾でのみ使用できます。 この制限は、サブクエリではなく、最上位のクエリで UNIONEXCEPT、および INTERSECT を指定する場合にのみ適用されます。 以下の「 Examples 」セクションを参照してください。

ORDER BY句は、TOP句または OFFSET 句とFETCH句も指定されていない限り、ビュー、インライン関数、派生テーブル、サブクエリでは有効ではありません。 これらのオブジェクトで ORDER BY が使用されている場合、句は、 TOP 句または OFFSET 句と FETCH 句によって返される行を決定するためにのみ使用されます。 ORDER BY句は、クエリ自体にもORDER BYが指定されていない限り、これらのコンストラクトのクエリ時に順序付けされた結果を保証しません。

OFFSETFETCHは、インデックス付きビューまたは CHECK OPTION 句を使用して定義されたビューではサポートされていません。

OFFSETFETCHは、次の制限事項を使用してTOPおよびORDER BYできる任意のクエリで使用できます。

  • OVER句は、OFFSETFETCHをサポートしていません。

  • OFFSETFETCHは、INSERTUPDATEMERGE、およびDELETEステートメントでは直接指定できませんが、これらのステートメントで定義されているサブクエリで指定できます。 たとえば、INSERT INTO SELECT ステートメントでは、SELECT ステートメントでOFFSETFETCHを指定できます。

  • UNIONEXCEPT、またはINTERSECT演算子を使用するクエリでは、OFFSETFETCHは、クエリ結果の順序を指定する最後のクエリでのみ指定できます。

  • TOP は、同じクエリ式 (同じクエリ スコープ内) で OFFSET および FETCH と組み合わせることはできません。

OFFSET と FETCH を使用して返される行を制限する

クエリ ページング ソリューションを実装し、クライアント アプリケーションに送信される行数を制限するには、TOP 句の代わりに OFFSET 句と FETCH 句を使用する必要があります。

ページング ソリューションとして OFFSETFETCH を使用するには、クライアント アプリケーションに返されるデータの ページ ごとにクエリを 1 回実行する必要があります。 たとえば、クエリの結果を 10 行ずつ返すには、クエリを 1 回実行して行 1 から 10 を返し、もう一度クエリを実行して行 11 から 20 などを返す必要があります。 各クエリは独立しており、相互に関連付けられることはありません。 つまり、クエリを 1 回実行してサーバーで状態を維持するカーソルを使用する場合とは異なり、状態の追跡はクライアント アプリケーションで行われます。 OFFSETFETCHを使用してクエリ要求間で安定した結果を得るには、次の条件を満たす必要があります。

  1. クエリで使用される基になるデータが変更されていない。 つまり、クエリによって操作された行が更新されないか、クエリからのページに対するすべての要求が、スナップショットまたはシリアル化可能なトランザクション分離を使用して 1 つのトランザクションで実行されます。 これらのトランザクション分離レベルの詳細については、「 SET TRANSACTION ISOLATION LEVELを参照してください。

  2. ORDER BY句には、一意であることが保証される列または列の組み合わせが含まれています。

この記事の後半の「例」セクションの「1 つのトランザクションで複数のクエリを実行する」の例を参照してください。

ページング ソリューションで一貫性のある実行プランが重要な場合は、OFFSETパラメーターとFETCH パラメーターにOPTIMIZE FORクエリ ヒントを使用することを検討してください。 この記事の後半の「Examples」セクションの「OFFSET 値と FETCH 値のSpecify 式」を参照してください。 OPTIMIZE FORの詳細については、Query ヒントを参照してください。

この記事の Transact-SQL コード サンプルは AdventureWorks2022 または AdventureWorksDW2022 サンプル データベースを使用します。このサンプル データベースは、Microsoft SQL Server サンプルとコミュニティ プロジェクトのホーム ページからダウンロードできます。

カテゴリ 主な構文要素
基本構文 ORDER BY
昇順と降順を指定する DESC または ASC
照合順序を指定する COLLATE
条件付き順序を指定する CASE
ランク付け関数で ORDER BY を使用する 順位付け関数
返される行数を制限する OFFSET および FETCH
UNION、EXCEPT、INTERSECT で ORDER BY を使用する UNION

基本構文

このセクションの例では、最低限必要な構文を使用して、 ORDER BY 句の基本的な機能を示します。

A. 選択リストで定義されている 1 つの列を指定する

次の例では、数値の ProductID 列を基準に結果セットを並べ替えます。 特定の並べ替え順序が指定されていないため、既定の (昇順) が使用されます。

USE AdventureWorks2022;
GO

SELECT ProductID, Name
FROM Production.Product
WHERE Name LIKE 'Lock Washer%'
ORDER BY ProductID;

B. 選択リストで定義されていない列を指定する

次の例では、選択リストに含まれていないが、 FROM 句で指定されたテーブルで定義されている列で結果セットを並べ替えます。

USE AdventureWorks2022;
GO

SELECT ProductID, Name, Color
FROM Production.Product
ORDER BY ListPrice;

C: 並べ替え列としてエイリアスを指定する

次の例では、列の別名 SchemaName を並べ替え列として指定します。

USE AdventureWorks2022;
GO

SELECT name, SCHEMA_NAME(schema_id) AS SchemaName
FROM sys.objects
WHERE type = 'U'
ORDER BY SchemaName;

D. 並べ替え列として式を指定する

次の例では、式を並べ替え列として使用します。 式は、 DATEPART 関数を使用して、従業員が採用された年で結果セットを並べ替えることによって定義されます。

USE AdventureWorks2022;
GO

SELECT BusinessEntityID, JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY DATEPART(year, HireDate);

昇順および降順の並べ替え順序を指定する

A. 降順を指定する

次の例では、数値列 ProductID を基準に、結果セットを降順で並べ替えます。

USE AdventureWorks2022;
GO

SELECT ProductID, Name
FROM Production.Product
WHERE Name LIKE 'Lock Washer%'
ORDER BY ProductID DESC;

B. 昇順を指定する

次の例では、Name 列を基準に、結果セットを昇順で並べ替えます。 文字は数字ではなくアルファベット順に並べ替えられます。 つまり、10 の位置は、2 の前になります。

USE AdventureWorks2022;
GO

SELECT ProductID, Name
FROM Production.Product
WHERE Name LIKE 'Lock Washer%'
ORDER BY Name ASC;

C: 昇順と降順の両方を指定する

次の例では、2 つの列を基準に結果セットを並べ替えます。 クエリの結果セットは、まず FirstName 列を基準に昇順で並べ替えられた後、LastName 列を基準に降順で並べ替えられます。

USE AdventureWorks2022;
GO

SELECT LastName, FirstName
FROM Person.Person
WHERE LastName LIKE 'R%'
ORDER BY FirstName ASC, LastName DESC;

照合順序を指定する

次の例は、 ORDER BY 句で照合順序を指定すると、クエリ結果が返される順序を変更する方法を示しています。 作成されるテーブルには、大文字と小文字、およびアクセントを区別しない照合順序で定義された列が含まれます。 さまざまなケースとアクセントの違いを含む値が挿入されます。 照合順序は ORDER BY 句で指定されていないため、最初のクエリでは、値を並べ替えるときに列の照合順序が使用されます。 2 番目のクエリでは、 ORDER BY 句で大文字と小文字が区別され、アクセントを区別する照合順序が指定され、行が返される順序が変更されます。

USE tempdb;
GO

CREATE TABLE #t1 (name NVARCHAR(15) COLLATE Latin1_General_CI_AI);
GO

INSERT INTO #t1
VALUES (N'Sánchez'),
    (N'Sanchez'),
    (N'sánchez'),
    (N'sanchez');

-- This query uses the collation specified for the column 'name' for sorting.
SELECT name
FROM #t1
ORDER BY name;

-- This query uses the collation specified in the ORDER BY clause for sorting.
SELECT name
FROM #t1
ORDER BY name COLLATE Latin1_General_CS_AS;

条件付き順序を指定する

次の例では、ORDER BY句でCASE式を使用して、指定された列値に基づいて行の並べ替え順序を条件付きで決定します。 最初の例では、SalariedFlag テーブルの HumanResources.Employee 列の値を評価します。 SalariedFlag が 1 に設定されている従業員は BusinessEntityID の降順で、 SalariedFlag が 0 に設定されている従業員は BusinessEntityID の昇順で返されます。 2 番目の例では、TerritoryName 列が 'United States' と等しい場合は結果セットが CountryRegionName 列の順序に従って並べ替えられ、他のすべての列は CountryRegionName の順序に従って並べ替えられます。

SELECT BusinessEntityID,
    SalariedFlag
FROM HumanResources.Employee
ORDER BY
    CASE SalariedFlag
        WHEN 1 THEN BusinessEntityID
    END DESC,
    CASE 
        WHEN SalariedFlag = 0 THEN BusinessEntityID
    END;
GO
SELECT BusinessEntityID,
    LastName,
    TerritoryName,
    CountryRegionName
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL
ORDER BY
    CASE CountryRegionName
        WHEN 'United States' THEN TerritoryName
        ELSE CountryRegionName
    END;

ランク付け関数で ORDER BY を使用する

次の例では、ランク付け関数ROW_NUMBERRANKDENSE_RANK、およびNTILEORDER BY句を使用します。

USE AdventureWorks2022;
GO

SELECT p.FirstName,
    p.LastName,
    ROW_NUMBER() OVER (ORDER BY a.PostalCode) AS "Row Number",
    RANK() OVER (ORDER BY a.PostalCode) AS "Rank",
    DENSE_RANK() OVER (ORDER BY a.PostalCode) AS "Dense Rank",
    NTILE(4) OVER (ORDER BY a.PostalCode) AS "Quartile",
    s.SalesYTD,
    a.PostalCode
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p
    ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
    ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
    AND SalesYTD <> 0;

返される行数を制限する

適用対象: SQL Server 2012 (11.x) 以降のバージョン、Azure SQL Database、および Azure SQL Managed Instance。

次の例では、 OFFSETFETCH を使用して、クエリによって返される行の数を制限します。

A. OFFSET 値と FETCH 値に整数定数を指定する

次の例では、 OFFSET 句と FETCH 句の値として整数定数を指定します。 最初のクエリにより、DepartmentID 列で並べ替えられたすべての行が返されます。 このクエリによって返される結果と、後の 2 つのクエリの結果を比べてみてください。 次のクエリでは、句 OFFSET 5 ROWS を使用して最初の 5 行をスキップし、残りのすべての行を返します。 最後のクエリでは、OFFSET 0 ROWS 句を使用して最初の行から処理を開始した後、FETCH NEXT 10 ROWS ONLY を使用して、返される行を、並べ替えられた結果セットからの 10 行に制限します。

USE AdventureWorks2022;
GO

-- Return all rows sorted by the column DepartmentID.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID;

-- Skip the first 5 rows from the sorted result set and return all remaining rows.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID OFFSET 5 ROWS;

-- Skip 0 rows and return only the first 10 rows from the sorted result set.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY;

B. OFFSET 値と FETCH 値の変数を指定する

次の例では、変数の @RowsToSkip@FetchRows を宣言し、 OFFSET 句と FETCH 句でこれらの変数を指定します。

USE AdventureWorks2022;
GO

-- Specifying variables for OFFSET and FETCH values
DECLARE
    @RowsToSkip TINYINT = 2,
    @FetchRows TINYINT = 8;

SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC OFFSET @RowsToSkip ROWS
FETCH NEXT @FetchRows ROWS ONLY;

C: OFFSET 値と FETCH 値の式を指定する

次の例では、式 @StartingRowNumber - 1 を使用して OFFSET 値を指定し、式を @EndingRowNumber - @StartingRowNumber + 1 して FETCH 値を指定します。 さらに、クエリ ヒント ( OPTIMIZE FOR) が指定されます。 このヒントにより、クエリをコンパイルおよび最適化するときにローカル変数に特定の値を指定できます。 この値はクエリを最適化する過程でのみ使用され、クエリの実行時には使用されません。 詳細については、 Query ヒントを参照してください。

USE AdventureWorks2022;
GO

-- Specifying expressions for OFFSET and FETCH values
DECLARE
    @StartingRowNumber TINYINT = 1,
    @EndingRowNumber TINYINT = 8;

SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC OFFSET @StartingRowNumber - 1 ROWS
FETCH NEXT @EndingRowNumber - @StartingRowNumber + 1 ROWS ONLY
OPTION (OPTIMIZE FOR (@StartingRowNumber = 1, @EndingRowNumber = 20));

D. OFFSET 値と FETCH 値に定数スカラー サブクエリを指定する

次の例では、定数スカラー サブクエリを使用して、 FETCH 句の値を定義します。 サブクエリにより、PageSize テーブルの dbo.AppSettings 列から 1 つの値が返されます。

-- Specifying a constant scalar subquery
USE AdventureWorks2022;
GO

CREATE TABLE dbo.AppSettings (
    AppSettingID INT NOT NULL,
    PageSize INT NOT NULL
);
GO

INSERT INTO dbo.AppSettings
VALUES (1, 10);
GO

DECLARE @StartingRowNumber TINYINT = 1;

SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC OFFSET @StartingRowNumber ROWS
FETCH NEXT (
    SELECT PageSize
    FROM dbo.AppSettings
    WHERE AppSettingID = 1
) ROWS ONLY;

E. 1 つのトランザクションで複数のクエリを実行する

次の例は、クエリのすべての要求で一貫性のある結果が返されるようにするページング ソリューションを実装する方法の 1 つを示しています。 クエリはスナップショット分離レベルを使用して 1 つのトランザクションで実行され、 ORDER BY 句で指定された列によって列の一意性が確保されます。

USE AdventureWorks2022;
GO

-- Ensure the database can support the snapshot isolation level set for the query.
IF (
    SELECT snapshot_isolation_state
    FROM sys.databases
    WHERE name = N'AdventureWorks2022'
) = 0
ALTER DATABASE AdventureWorks2022
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

-- Set the transaction isolation level  to SNAPSHOT for this query.
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
GO

-- Beginning the transaction.
BEGIN TRANSACTION;
GO

-- Declare and set the variables for the OFFSET and FETCH values.
DECLARE
    @StartingRowNumber INT = 1,
    @RowCountPerPage INT = 3;

-- Create the condition to stop the transaction after all rows have been returned.
WHILE (
    SELECT COUNT(*)
    FROM HumanResources.Department
) >= @StartingRowNumber
BEGIN
    -- Run the query until the stop condition is met.
    SELECT DepartmentID, Name, GroupName
    FROM HumanResources.Department
    ORDER BY DepartmentID ASC OFFSET @StartingRowNumber - 1 ROWS
    FETCH NEXT @RowCountPerPage ROWS ONLY;

    -- Increment @StartingRowNumber value.
    SET @StartingRowNumber = @StartingRowNumber + @RowCountPerPage;

    CONTINUE
END;
GO

COMMIT TRANSACTION;
GO

UNION、EXCEPT、INTERSECT で ORDER BY を使用する

クエリで UNIONEXCEPT、または INTERSECT 演算子を使用する場合は、ステートメントの末尾に ORDER BY 句を指定する必要があり、結合されたクエリの結果が並べ替えられます。 次の例では、赤色または黄色のすべての製品が返され、この結合リストが ListPrice 列を基準に並べ替えられます。

USE AdventureWorks2022;
GO

SELECT Name, Color, ListPrice
FROM Production.Product
WHERE Color = 'Red'
-- ORDER BY cannot be specified here.

UNION ALL

SELECT Name, Color, ListPrice
FROM Production.Product
WHERE Color = 'Yellow'
ORDER BY ListPrice ASC;

例: Azure Synapse Analytics、Analytics Platform System (PDW)

次の例は、EmployeeKey の数値列を昇順で並べ替えた結果セットの順序付けを示しています。

-- Uses AdventureWorks
SELECT EmployeeKey, FirstName, LastName
FROM DimEmployee
WHERE LastName LIKE 'A%'
ORDER BY EmployeeKey;

次の例では、EmployeeKey の数値列を基準に降順で結果セットを並べ替えます。

-- Uses AdventureWorks
SELECT EmployeeKey, FirstName, LastName
FROM DimEmployee
WHERE LastName LIKE 'A%'
ORDER BY EmployeeKey DESC;

次の例では、LastName 列を基準に結果セットを並べ替えます。

-- Uses AdventureWorks
SELECT EmployeeKey, FirstName, LastName
FROM DimEmployee
WHERE LastName LIKE 'A%'
ORDER BY LastName;

次の例では、2 つの列を基準に並べ替えます。 このクエリでは、FirstName 列で昇順に並べ替えを行ってから、FirstName 列の共通の LastName 値を降順に並べ替えます。

-- Uses AdventureWorks
SELECT EmployeeKey, FirstName, LastName
FROM DimEmployee
WHERE LastName LIKE 'A%'
ORDER BY LastName, FirstName;