3

最近のプログラミングのインタビューで、私は SQL の質問をされ、それに対して妥当な答えだと思いましたが、私の答えはデータベース管理者から強い反対を受け、その理由を理解することができませんでした。

それ以来、私はこの問題についてもう少し考えてみましたが、自分の答えの何が恐ろしいのか理解できませんでした。そのため、レポートを作成するための正しい方法、または失敗した場合のより良い方法を見つけるために、ここで啓蒙を求めています。図書館のテーブルと本のテーブルを含むデータベースからのライブラリの数とその中の本の数。

文言がインタビューの質問と同じにならないように、シナリオを少し変更しましたが、タスクは同じです。

問題の最小限のスキーマを次に示します。

create table library (
  id integer primary key,
  name char(8)
);

create table book (
  id integer primary key,
  name char(8),
  library_id integer,
  foreign key (library_id) references library(id)
);

課題は、2 冊以上の本がある図書館について、図書館の名前とその中の本の数をリストすることです。

そして、ここに私の提案する解決策があります:

select
  a.name as name,
  b.nbooks as nbooks
from
    library as a,
    (
        select
            min(library_id) as library,
            count(id) as nbooks
        from
            book
        group by 
            library_id
    ) as b
where
    ( nbooks > 1 ) and (a.id = b.library)
;

考え直して、明示的な使用のinner join方が良いかもしれません。それ以外に、(一般的に、または特定のデータベースに関連して) 潜在的な落とし穴と、このレポートを生成する正しい方法を教えてください。

4

3 に答える 3

4

これを行う簡単な方法を次に示します。

select l.name, count(*) as numbooks
from library l join
     books b
     on l.id = b.library_id
group by l.name
having count(*) > 1

あなたの答えは技術的には問題ありません。DBA はおそらく、他の人が考える特定のスタイル上の事柄 (ライブラリーのエイリアスとして "l" ではなく "a" を使用するなど) を気にしません。サブクエリは不要であり、min(library_id)不要として突き出ています。集計関数を group by 列に適用できますが、通常は実行されません。

最大の問題 (DBA が対応している可能性があります) は、WHERE句ではなく句に結合条件があるONことです。これを省略したり、無害な変更を加えたりすると、クエリが INNER JOIN ではなく CROSS JOIN になる可能性があるため、これは危険です。

于 2012-10-02T14:31:31.320 に答える
2

少なくともいくつかの重大な問題が見られます。1) ANSIJOIN構文を使用していない、2) グループ化しlibrary_idて集計関数を使用している。

必要に応じて追加のライブラリ列を返しながらクエリを実行する方法を知っていることを示すために、次のように記述します。

select l.lid, l.name, b.Count
from library l 
inner join (
    select library_id, count(*) as Count
    from books
    group by library_id
    having Count > 1 
) b on l.lid = b.library_id 

また、2 つのライブラリが同じ名前である場合に備えて、特にライブラリ名でグループ化しなかったことも指摘しておきます。

于 2012-10-02T14:35:44.127 に答える
0

DBA が気に入らなかったのは、おそらくサブ SELECT でした。これらは通常、パフォーマンスが非常に悪いため、可能な限り避ける必要があります (コード形式でも醜く見えます)。

この場合、JOIN を使用したほうがよいでしょう。

SELECT library.name AS library
       count( book.id ) AS books
  FROM library
  JOIN book ON book.library_id = library.id
  GROUP BY book.id
  HAVING count( book.id ) > 1
于 2012-10-02T14:38:00.117 に答える