5

私は恐ろしいレガシーデータベースを正規化するという苦痛を経験しており、DBMS のバグであると思われるものを発見しました。

このクエリは、期待どおりの結果を返します。

SELECT DISTINCT RIGHT(SQUEEZE(thing_id), 2) AS thing_id, TRIM(thing_name)
FROM thing
ORDER BY thing_id, thing_name;
(16 rows)

初めてクエリを実行したとき、次のように、ORDER BY で誤って間違った列を使用してしまいました。

SELECT DISTINCT RIGHT(SQUEEZE(thing_id), 2) AS thing_id, TRIM(thing_name)
FROM thing
ORDER BY thing_name, location;
(33 rows)

変更するのは ORDER BY だけであり、返される行数が 16 から 33 に増加することに注意してください。それが与える結果は、クエリが指定する DISTINCT ではありません。

これは完全なバグだと思いますが、「場所」で注文すると、結果に表示されずに選択されてしまうため、同僚は正常であると言っています。

ORDER BY は、SELECT クエリで返される行数に影響を与える必要がありますか?

編集:別の人にクエリを見てもらい、クエリを2つの別々のファイルにコピーしてから、それらに対してdiffコマンドを実行しました。2 つのクエリの唯一の違いは、ORDER BY にリストされている列であることは 100% 確実です。

更新: Ingres は、バグ修正を含むパッチ 14301 をリリースして以来、次のように述べています。

つまり、結果が正しくないため、問題のクエリはエラーになります。

4

4 に答える 4

6

問題は、2 番目のクエリの列 ( location) がリストORDER BYに含まれていないことですSELECT DISTINCT。実際には、どちらのクエリも無効な SQL です (Ingres では許可されているようですが)。私はそれらを次のように単純化しました(最初のものは問題ありません)。

クエリ 1 (有効な SQL):

SELECT DISTINCT 
      thing_id 
    , thing_name
FROM thing
ORDER BY thing_id
       , thing_name ;

クエリ 2 (無効な SQL、エラーが発生するはずです):

SELECT DISTINCT 
      thing_id 
    , thing_name
FROM thing
ORDER BY thing_name
       , location;

なぜエラーが発生するのですか?は と の後にORDER BY処理する必要があるためです。そのため、元のテーブルの 2 つ以上の行に同じものと異なるものがある場合があります。これらの行は 1 つに折りたたまれます。そのため、順序付けに使用する場所の値はありません。(隠された場所の値) が保持されていたとしても、多くある中でどれを保持する必要がありますか?SELECTDISTINCTthing_idthing_namelocation

SELECT DISTINCTSELECT ALLクエリはandで書き直すことができますGROUP BY(この場合も無効です):

SELECT ALL
      thing_id 
    , thing_name
FROM thing
GROUP BY thing_id 
       , thing_name
ORDER BY thing_name
       , location;

上記 (クエリ 2) は、実際には PostgreSQL、SQL-Server、および Oracle でエラーを生成します。SQL-Fiddleでテストする


Ingres の 2 番目のクエリによって返された誤った行数から、バックグラウンドで起こっていることは、彼locationが秘密裏にSELECTリストに保持されているため、それを使用して削除できると推測ORDER BYされます。DISTINCTこれは、非標準のバグのある動作の結果と組み合わせて:

SELECT DISTINCT 
      thing_id 
    , thing_name
   (, location         --- hidden column) 
FROM thing
ORDER BY thing_name
       , location;

それをバグと呼ぶことも、機能と呼ぶこともできますが、そもそもそれが実際に許可されるべきではないことを知っている限り、問題ではありません。

同様の問題が 1 年前に Actian フォーラムで報告されたようです: DISTINCT + ORDER BY の問題で、修正されたと思われます。彼らが参照しているバージョン、または実際に修正されているかどうか (および「修正」の意味) はわかりません。


クエリを有効にして期待どおりに動作させたい場合は、次のようなものを使用できます。

SELECT
      RIGHT(SQUEEZE(thing_id), 2)  AS squeezed_thing_id
    , TRIM(thing_name)             AS trimmed_thing_name 
    , MIN(location)                AS a_location            --- or MAX()
FROM 
    thing
GROUP BY 
      RIGHT(SQUEEZE(thing_id), 2)
    , TRIM(thing_name)     
ORDER BY 
      trimmed_thing_name
    , a_location ;                
于 2012-05-09T23:10:30.900 に答える
3

いいえ、返される行数には影響しorder byません。

あなたの言っていることが本当なら、それは非常に奇妙で根本的なバグです。Ingres の担当者にメールを送信する前に、両方のクエリの戻り列を 3 回 (次に 4 回) チェックして、これが単純なユーザー エラーではないことを完全に確認します。

編集

実際には、バックアップ データベースでもクエリを実行してみます。利用可能なバックアップがない場合は、既存のデータベースをコピーすることで解決できる可能性があります (Ingres がサポートしている場合)。

以前、ハードウェアに障害のあるマシンで無意味な結果を返すクエリがありました。必ず確認したい項目です。

于 2012-05-09T22:26:25.443 に答える
3

SQL での操作の順序は次のとおりです。

FROM > WHERE > GROUP BY > HAVING > SELECT > ORDER BY

これは確かにバグのようです。どの DBMS ですか?

于 2012-05-09T22:27:09.643 に答える
0

location最初のクエリに追加すると、両方が同じ数の行を返します。2 番目のクエリがより多くの行を返す理由は、そのクエリで選択していないためlocationです。前述のように、一部の RDBMS では許可されていませんが、Ingres では許可されています。おそらくSQL 標準で禁止されていないためでしょうか?.

于 2012-05-19T09:42:25.363 に答える