3

Oracleempテーブルを考えてみましょう。と で最高の給与を持つ従業員を取得したいと思いdepartment = 20ますjob = clerk。また、「empno」列がなく、主キーに多数の列が含まれているとします。これは次の方法で実行できます。

select * from scott.emp
where deptno = 20 and job = 'CLERK'
and sal =  (select max(sal) from scott.emp
            where deptno = 20 and job = 'CLERK')

これは機能しますが、テスト deptno = 20 と job = 'CLERK' を複製する必要があり、これは避けたいと考えています。これを書くためのよりエレガントな方法はありgroup byますか? ところで、これが重要な場合、私は Oracle を使用しています。

4

6 に答える 6

3

以下はやや過剰に設計されていますが、「上位 x」クエリに適した SQL パターンです。

SELECT 
 * 
FROM 
 scott.emp
WHERE 
 (deptno,job,sal) IN
 (SELECT 
   deptno,
   job,
   max(sal) 
  FROM 
   scott.emp
  WHERE 
   deptno = 20 
   and job = 'CLERK'
  GROUP BY 
   deptno,
   job
  )

また、これは Oracle と Postgress (私は思う) では機能しますが、MS SQL では機能しないことに注意してください。MS SQL で同様のものについては、最新の価格を取得するための質問 SQL クエリを参照してください。

于 2008-09-09T01:58:32.883 に答える
2

対象となるデータベースが確かな場合は、Mark Nold のソリューションを使用しますが、方言に依存しない SQL* が必要な場合は、試してください。

SELECT * 
FROM scott.emp e
WHERE e.deptno = 20 
AND e.job = 'CLERK'
AND e.sal = (
  SELECT MAX(e2.sal) 
  FROM scott.emp e2
  WHERE e.deptno = e2.deptno 
  AND e.job = e2.job
)

*これはどこでも機能すると思いますが、テストする環境がありません。

于 2008-09-09T08:00:40.893 に答える
1

Oracleでは、分析関数を使用して実行するため、empテーブルにクエリを実行するのは1回だけです。

SELECT *
  FROM (SELECT e.*, MAX (sal) OVER () AS max_sal
          FROM scott.emp e
         WHERE deptno = 20 
           AND job = 'CLERK')
 WHERE sal = max_sal

シンプルで読みやすく、効率的です。

すべての部門のこの情報をリストリストするように変更する場合は、OVERで「PARTITIONBY」句を使用する必要があります。

SELECT *
  FROM (SELECT e.*, MAX (sal) OVER (PARTITION BY deptno) AS max_sal
          FROM scott.emp e
         WHERE job = 'CLERK')
 WHERE sal = max_sal
ORDER BY deptno
于 2008-09-15T14:04:05.790 に答える
0

多くの解決策があります。テーブルエイリアスを追加して列名を結合するだけで元のクエリレイアウトを維持することもできますが、クエリには DEPTNO = 20 と JOB = 'CLERK' が 1 回しかありません。

SELECT 
  * 
FROM 
  scott.emp emptbl
WHERE
  emptbl.DEPTNO = 20 
  AND emptbl.JOB = 'CLERK'
  AND emptbl.SAL =  
    (
      select 
        max(salmax.SAL) 
      from 
        scott.emp salmax
      where 
        salmax.DEPTNO = emptbl.DEPTNO
        AND salmax.JOB = emptbl.JOB
    )

また、キーワード「ALL」をこれらのタイプのクエリに使用すると、「MAX」機能を削除できることにも注意してください。

SELECT 
  * 
FROM 
  scott.emp emptbl
WHERE
  emptbl.DEPTNO = 20 
  AND emptbl.JOB = 'CLERK'
  AND emptbl.SAL >= ALL  
    (
      select 
        salmax.SAL
      from 
        scott.emp salmax
      where 
        salmax.DEPTNO = emptbl.DEPTNO
        AND salmax.JOB = emptbl.JOB
    )

それが役に立ち、理にかなっていることを願っています。

于 2008-09-11T20:39:04.983 に答える
0

それは素晴らしいことです!(x, y, z) と SELECT ステートメントの結果を比較できるとは知りませんでした。これは Oracle とうまく連携します。

他の読者への補足として、上記のクエリには「(deptno,job,sal)」の後に「=」がありません。スタック オーバーフロー フォーマッタが食べたのかもしれません (?)。

繰り返しますが、マークに感謝します。

于 2008-09-09T03:24:11.430 に答える
0

Oracle では、EXISTS ステートメントを使用することもできます。これは場合によってはより高速です。

たとえば... SELECT name, number FROM cust WHERE cust IN ( SELECT cust_id FROM big_table ) AND enter > SYSDATE -1 は遅くなります。

ただし、SELECT name, number FROM cust c WHERE EXISTS ( SELECT cust_id FROM big_table WHERE cust_id=c.cust_id ) AND enter > SYSDATE -1 は、適切なインデックスを使用すると非常に高速になります。これを複数のパラメーターで使用することもできます。

于 2008-09-09T11:51:12.977 に答える