sql выбирает только первые 3 строки из второй таблицы

#sql #oracle

#sql #Oracle

Вопрос:

Мне нужно всего 3 записи из дочерней таблицы.

 CREATE TABLE project
    (prj_code int , prj_name varchar(255) );


CREATE TABLE task
    (id int , prj_code int, task_name varchar(255) );

INSERT INTO project VALUES (1,'myproj1');    
INSERT INTO project VALUES (2,'myproj2');

INSERT INTO task VALUES (1,1,'testing');
INSERT INTO task VALUES (2,1,'prod');
INSERT INTO task VALUES (3,1,'prod2');
INSERT INTO task VALUES (4,1,'testing2');

INSERT INTO task VALUES (5,2,'mytask1');
INSERT INTO task VALUES (6,2,'mytask2');
  

Пожалуйста, посмотрите на скрипку

Редактировать:

Хотите создать сводную таблицу, чтобы получить идентификаторы 3 самых маленьких задач в столбцах для каждого проекта

Комментарии:

1. В чем вопрос? Что вы пробовали?

2. результирующий набор должен составлять одну строку на запись проекта.

3. Мне нужны 3 последние записи из table — task для каждой совпадающей записи из project table.

4. По-прежнему нет вопросов, которые я вижу.

5. Концепция first и last здесь не определена. Первая и последняя на основе какого фактора?

Ответ №1:

Этот код делает свое дело. Вам нужно использовать RANK для выбора 3 самых маленьких идентификаторов, а затем сводной таблицы:

 WITH tasks AS (
select 
   A.prj_code,
   prj_name,
   RANK() OVER (PARTITION BY A.PRJ_CODE ORDER BY ID ) RANK, 
   ID, 
   TASK_NAME
from task A
inner join project B
   on A.PRJ_CODE = B.PRJ_CODE
order by A.prj_code)


select PRJ_CODE, prj_name, sum(T1) T1, sum(T2) T2, sum(T3) T3
from tasks A
PIVOT (max(ID) for RANK IN ('1' as T1 ,'2' as T2 ,'3' as T3 )) B
GROUP BY PRJ_CODE, prj_name
  

или

используйте приведенный ниже код для получения имен задач

 select PRJ_CODE, prj_name, max(T1) T1, max(T2) T2, max(T3) T3
from tasks A
PIVOT (max(TASK_NAME) for RANK IN ('1' as T1 ,'2' as T2 ,'3' as T3 )) B
GROUP BY PRJ_CODE, prj_name
  

SQLFiddle

Комментарии:

1. Хорошая практическая демонстрация функции pivot.

Ответ №2:

Это отвратительное решение, но я думаю, что оно иллюстрирует способ достижения этой цели. Я не предполагаю никаких возможностей поворота, не зная, какую версию Oracle вы используете.

 with tasks as (
  select
    a.prj_code, a.prj_name,
    b.id, b.task_name,
    row_number() over (partition by a.prj_code order by b.id) as rn
  from
    project a
    join task b on
      a.prj_code = b.prj_code
), pivotdata as (
  select
    prj_code, prj_name,
    case when rn = 1 then task_name end as task_1,
    case when rn = 2 then task_name end as task_2,
    case when rn = 3 then task_name end as task_3
  from tasks
)
select
  prj_code, prj_name,
  max (task_1) as task_1, max (task_2) as task_2,
  max (task_3) as task_3
from pivotdata
group by
  prj_code, prj_name
  

Вывод:

 Prj Code   Prj Name    Task 1   Task 2  Task 3
1          myproj1     testing  prod    prod2
2          myproj2     mytask1  mytask2