Специальный запрос условия SQL для поиска первых двух записей и последней? - PullRequest
0 голосов
/ 28 сентября 2018

У меня есть такой набор данных:

 student_id     date     project_id
 1              1/1/18   15
 1              1/1/18   17
 1              2/2/18   16 
 1              3/3/18   15 
 1              3/3/18   12 
 2              2/3/18   3
 2              4/3/18   4
 2              5/3/18   6 
 2              5/3/18   4 

Я хочу найти идентификатор студента с двумя первыми проектами, которые они сделали, и последними, которые они сделали с датой,

student_id    project_id1st    date1st     project_id2nd      date2nd projectlast    datelast
1             15               1/1/18      17                 1/1/18  12               3/3/18
2             3                2/3/18      4                  4/3/18  4                5/3/18

Во-первыхЯ хочу решить это в пандах, но получил плохой результат.Тогда я попытался решить это в SQL.

WITH abc AS (
  SELECT student_id, project_id, date, 
         ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date) rn
  FROM table 
)
SELECT student_id, 
       SUM(CASE WHEN rn = 1 THEN abc.project_id END) as firstid,
       SUM(CASE WHEN rn = 2 THEN abc.project_id END) as secondsid,
       MIN(CASE WHEN rn = 1 THEN date END) as first,
       MIN(CASE WHEN rn = 2 THEN date END) as second
FROM abc
GROUP BY 1;

Я получил хороший результат, но каким-то образом он перепутался с порядком набора данных, используя ROW_NUMBER().Например, с точки зрения студента 1, project_id 17, имеющий значение 1 в rownumber, project_id 15 станет второй датой начала.

Ответы [ 4 ]

0 голосов
/ 28 сентября 2018

Ваша проблема в том, что у вас нет столбца, в котором указан правильный порядок.В рамке окна row_number вы даете order by date.Но когда в кадре много строк, результат получается совершенно случайным.

Вы должны указать базе данных, что делать со строками в одном кадре.Хотели бы вы взять project_id?Нет такого индикатора, как «сырой заказ».

Например,

SELECT * FROM table

никогда не дает выделенный порядок (например, порядок вставки наборов данных).Результирующий набор может быть упорядочен совершенно случайно.То же самое для любого окна фрейма, которое вы определяете.

Поэтому вам понадобится способ (столбец или алгоритм), обеспечивающий ожидаемый порядок.


Если вы возьмете ORDER BY date, project_id тогда (например) кадр для 3/3/18 будет заказан с project_id 12, 15, который не является вашим "необработанным заказом".Если вы закажете его DESC, то ваш 1/1/18 кадр будет упорядочен неправильно, потому что первый идентификатор будет 17.Так что project_id не является хорошим критерием порядка.Но другой возможности для заказа нет.Это потому, что вам нужен еще один столбец.

Чтобы получить «необработанный заказ», можно использовать столбец идентификатора автоматического увеличения (введите serial - или в случае Postgres 10 и выше GENERATED AS IDENTITY -).


Если у вас есть определенный порядок (например, столбец идентификатора вставки), то это может быть ваш запрос:

WITH abc AS (
    SELECT insert_id, student_id, project_id, date, 
        ROW_NUMBER() OVER (PARTITION BY student_id ORDER BY insert_id) rn_asc,        -- A
        ROW_NUMBER() OVER (PARTITION BY student_id ORDER BY insert_id DESC) rn_desc   -- B
    FROM projects
)
SELECT 
    student_id,
    MAX(project_id) FILTER (WHERE rn_asc = 1),
    MAX(date) FILTER (WHERE rn_asc = 1),
    MAX(project_id) FILTER (WHERE rn_asc = 2),
    MAX(date) FILTER (WHERE rn_asc = 2),
    MAX(project_id) FILTER (WHERE rn_desc = 1),
    MAX(date) FILTER (WHERE rn_desc = 1)
FROM abc
GROUP BY student_id

A: Упорядочение кадров студента по возрастанию идентификатора идавая номера строк 1 и 2, которые помогают отфильтровать первые две строки.

B: упорядочить по убыванию, чтобы получить последнюю строку (которая в данном случае получает row number == 1)

демо: дБ <> скрипка

0 голосов
/ 28 сентября 2018

Я бы попытался сделать это с помощью простого объединения, например:

select min(date), max(date), t.bez, min(x.date) from table t
left join (
    SELECT date, student_id,
    ROW_NUMBER() OVER (PARTITION BY student_id ORDER BY date) rn
    FROM table
    group by date, student_id) x on x.student_id = t.student_id and x.rn = 2
group by t.student_id

Вы можете просто сгруппировать по дате и student_id в вашем ROW_Number (), чтобы вы не получили одну и ту же дату дважды

0 голосов
/ 28 сентября 2018

Использовать заказ по 2 столбцам project_id и дате

[Демо]

WITH abc AS (
  SELECT student_id, project_id, date, 
         ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date,project_id) rn
  FROM table 
)
SELECT student_id, 
       SUM(CASE WHEN rn = 1 THEN abc.project_id END) as firstid,
       SUM(CASE WHEN rn = 2 THEN abc.project_id END) as secondsid,
       MIN(CASE WHEN rn = 1 THEN date END) as first,
       MIN(CASE WHEN rn = 2 THEN date END) as second
FROM abc
GROUP BY 1;
0 голосов
/ 28 сентября 2018

Пожалуйста, попробуйте привести к целому числу.

С abc AS (ВЫБЕРИТЕ student_id, project_id, date,

CAST (ROW_NUMBER () OVER (PARTITION BY)user_id ORDER BY date) AS INT ) rn ИЗ таблицы)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...