web-dev-qa-db-ja.com

SELECT DISTINCTが指定されている場合、ORDER BYアイテムは選択リストに表示される必要があります

Selectリストの列をorder byリストに追加しましたが、それでもエラーが発生します。

SELECT DISTINCTが指定されている場合、ORDER BYアイテムが選択リストに表示されている必要があります。

ストアドプロシージャは次のとおりです。

CREATE PROCEDURE [dbo].[GetRadioServiceCodesINGroup] 
@RadioServiceGroup nvarchar(1000) = NULL
AS
BEGIN
SET NOCOUNT ON;

SELECT DISTINCT rsc.RadioServiceCodeId,
                rsc.RadioServiceCode + ' - ' + rsc.RadioService as RadioService
FROM sbi_l_radioservicecodes rsc
INNER JOIN sbi_l_radioservicecodegroups rscg 
ON rsc.radioservicecodeid = rscg.radioservicecodeid
WHERE rscg.radioservicegroupid IN 
(select val from dbo.fnParseArray(@RadioServiceGroup,','))
OR @RadioServiceGroup IS NULL  
ORDER BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService

END
62
Xaisoft

これを試して:

ORDER BY 1, 2

OR

ORDER BY rsc.RadioServiceCodeId, rsc.RadioServiceCode + ' - ' + rsc.RadioService
57

それらは同じものではありませんが、ある意味では、DISTINCTGROUP BYを意味します。すべてのDISTINCTGROUP BYを使用して書き換えることができるためですそれを念頭に置いて、集合グループにない何かで注文することは意味がありません。

たとえば、次のようなテーブルがある場合:

 col1 col2 
 ---- ---- 
 1 1 
 1 2 
 2 1 
 2 2 
 2 3 
 3 1 

そして、次のようにそれを照会してみてください:

SELECT DISTINCT col1 FROM [table] WHERE col2 > 2 ORDER BY col1, col2

couldが行ごとに複数のcol2値になるため、それは意味をなさないでしょう。注文にはどちらを使用する必要がありますか?もちろん、このクエリでは、結果がそのようにはならないことがわかりますが、データベースサーバーは事前にそれを知ることができません。

さて、あなたのケースは少し異なります。 order by句のすべての列をselect句に含めたため、一見するとすべてがグループ化されているように見えます。ただし、これらの列の一部は計算フィールドに含まれていました。 distinctと組み合わせてそれを行うと、distinctディレクティブをonlyを計算の最終結果に適用できます。もう計算のソース。

これは、サーバーがこれらの列を使用できることを実際には認識していないことを意味します。それらが使用されたことは知っていますが、計算操作が上記の最初の簡単な例に似た効果を引き起こす可能性があるかどうかはわかりません。

そのため、列を順序付けに使用できることをサーバーに伝えるために、何か他のことをする必要があります。それにはいくつかの方法がありますが、このアプローチはうまくいくはずです:

SELECT rsc.RadioServiceCodeId,
            rsc.RadioServiceCode + ' - ' + rsc.RadioService as RadioService
FROM sbi_l_radioservicecodes rsc
INNER JOIN sbi_l_radioservicecodegroups rscg 
    ON rsc.radioservicecodeid = rscg.radioservicecodeid
WHERE rscg.radioservicegroupid IN 
    (SELECT val FROM dbo.fnParseArray(@RadioServiceGroup,','))
    OR @RadioServiceGroup IS NULL  
GROUP BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService
ORDER BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService
47
Joel Coehoorn

次のいずれかを試してください。

  1. 列のエイリアスを使用:

    ORDER BY RadioServiceCodeId、RadioService

  2. 列の位置を使用:

    ORDER BY 1,2

DISTINCTクエリの結果に実際に表示される列のみを並べ替えることができます-基になるデータは並べ替えできません。

11
Tony Andrews

連結を定義するとき、DISTINCTと組み合わせて注文する場合は、新しい列にALIASを使用する必要がありますSome Ex with sql 2008

--this works 

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) as FullName 
    from SalesLT.Customer c 
    order by FullName

--this works too

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) 
    from SalesLT.Customer c 
    order by 1

-- this doesn't 

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) as FullName 
    from SalesLT.Customer c 
    order by c.FirstName, c.LastName

-- the problem the DISTINCT needs an order on the new concatenated column, here I order on the singular column
-- this works

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) 
        as FullName, CustomerID 
        from SalesLT.Customer c 

order by 1, CustomerID

-- this doesn't

    SELECT DISTINCT (c.FirstName + ' ' + c.LastName) as FullName 
     from SalesLT.Customer c 
      order by 1, CustomerID
3
rio

Distinct and Group Byは通常、異なる目的で同じ種類のことを行います...どちらも、グループ化されている(またはSelect Distinct句で選択されている)列に基づいてメモリに「作業」テーブルを作成し、それを設定しますクエリがデータを読み取り、値がそうする必要があることを示す場合にのみ新しい「行」を追加する作業テーブル.

唯一の違いは、Group Byには、Sum()、Count()、Avg()などの計算された集計フィールドの作業テーブルに追加の「列」があり、元の各行を更新する必要があることです。 Distinctはこれを行う必要はありません...個別の値を取得するためだけにグループ化する特別な場合(および出力に集計列がありません)、それはおそらくまったく同じクエリプランです... 2つのオプションのクエリ実行プランをレビューし、それが何をしたかを見るのは興味深いでしょう...

確かに明確なのは、それがあなたがしていることである場合、読みやすさを追求する方法です(目的が重複行を排除することであり、集計列を計算していない場合)

3
Charles Bretana

サブクエリを試すことができます:

SELECT DISTINCT TEST.* FROM (
    SELECT rsc.RadioServiceCodeId,
        rsc.RadioServiceCode + ' - ' + rsc.RadioService as RadioService
    FROM sbi_l_radioservicecodes rsc
       INNER JOIN sbi_l_radioservicecodegroups rscg ON  rsc.radioservicecodeid = rscg.radioservicecodeid
    WHERE rscg.radioservicegroupid IN 
       (select val from dbo.fnParseArray(@RadioServiceGroup,','))
        OR @RadioServiceGroup IS NULL  
    ORDER BY rsc.RadioServiceCode,rsc.RadioServiceCodeId,rsc.RadioService
) as TEST
0
HenryS