4

次のシナリオがあります。

テーブルの従業員:

First Name | Last Name | Department | Salary
-----------|-----------|------------|---------
John       | Doe       | Finance    | 20
John       | Doe       | R&D        | 20
John       | null      | Finance    | 20
John       | long      | Finance    | 20

そして、姓にnullがない限り、(First Name,Last Name)ごとに1行が必要です。次に、(First Name,null)を含む1行だけが必要です。

上記の例の場合、結果は次のようになります。

First Name | Last Name | Department | Salary
-----------|-----------|------------|---------
John       | null      | Finance    | 20

しかし、私がその記録を持っていなかった場合、結果は次のようになるはずです:

First Name | Last Name | Department | Salary
-----------|-----------|------------|---------
John       | Doe       | R&D        | 20
John       | long      | Finance    | 20

答えには Partition By-s が含まれていると思いますが、どこにあるのかわかりません。

今、私はこれに来ました:

SELECT FirstName,LastName, DEPARTMENT,Salary,RK FROM 
(
select * from 
    SELECT EXT.*, 
    ROW_NUMBER() OVER(PARTITION BY EXT.FirstName,EXT.LastName 
    ORDER BY rownum ASC) AS RK
      FROM Employees EXT   
)
WHERE RK = 1 ;

ありがとう !

4

3 に答える 3

8

問題は PARTITION 句にあります。少なくとも 1 つの姓が NULL でない限り、姓があるすべての名が必要です。この場合、姓が NULL の名のみが必要です。

ここでの答えは、 ROW_NUMBER()の代わりにRANK()を使用することです。RANK() は連続したリストを作成しません。代わりに、値が等しい行は同じランクになります。

select firstname, lastname, department, salary, rk 
  from ( select a.*
              , rank() over ( partition by firstname
                                  order by case when lastname is null then 0 
                                                else 1 
                                           end
                                           ) as rnk
           from employees a
                )
where rnk = 1

これは、姓自体ではなく、姓の存在を関連させることによって機能します。

さらに2つのポイント:

  1. 括弧なしでネストされた選択がありました。これはうまくいきません。
  2. ROWNUM による順序付けは意味がありません。定義により、rownum はステートメントによって返された順序で行を返します。つまり、行は常にROWNUM の順序になります。
于 2012-12-10T17:43:43.813 に答える
2

このようなもの:

SQL> create table person
  2  (
  3    fname varchar2(10),
  4    lname varchar2(10),
  5     dept  varchar2(10),
  6     sal   number
  7  );

Table created.

SQL> insert into person values ('John', 'Doe', 'Finance', 20);

1 row created.

SQL> insert into person values ('John', 'Doe', 'R&D', 20);

1 row created.

SQL> insert into person values ('John', '', 'Finance', 20);

1 row created.

SQL> insert into person values ('John', 'Long', 'Finance', 20);

1 row created.

SQL> insert into person values ('Paul', 'Doe', 'R&D', 30);

1 row created.

SQL> insert into person values ('Paul', 'Doe', 'Finance', 30);

1 row created.

SQL> insert into person values ('Paul', 'Long', 'Finance', 30);

1 row created.

SQL> select fname, lname, dept, sal
  2    from (select fname, lname, dept, sal,has_null,
  3                  row_number() over(partition by fname,
  4                                                  case when has_null = 'N' then lname else null end
  5                                    order by lname desc nulls first) rn
  6             from (select fname, lname,
  7                           nvl(max(case  when lname is null then 'Y'
  8                               end) over(partition by fname), 'N') has_null, dept, sal
  9                      from person))
 10   where rn = 1;

FNAME      LNAME      DEPT              SAL
---------- ---------- ---------- ----------
John                  Finance            20
Paul       Doe        R&D                30
Paul       Long       Finance            30
于 2012-12-10T17:39:44.250 に答える
0

そのクエリは (同じ) トリックを行いますが、より適切に実行されます。

SELECT fname, 
       lname, 
       dept, 
       sal 
FROM   (SELECT fname, 
               lname, 
               dept, 
               sal, 
               First_value(lname) 
                 OVER( 
                   partition BY fname 
                   ORDER BY lname nulls first) null_domain, 
               Row_number() 
                 OVER ( 
                   partition BY fname, lname 
                   ORDER BY fname)             r 
        FROM   person) 
    WHERE  ( ( null_domain IS NULL 
           AND lname IS NULL ) 
          OR null_domain IS NOT NULL ) 
        AND r = 1; 
于 2013-02-11T10:38:01.010 に答える