Нужна помощь в понимании диапазона между функциями окна SQL - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь понять, как работает предложение range в нижнем регистре (база данных Oracle)

SELECT
    EMPID,NAME, 
    HIRE_DATE_1, 
    SALARY,
    count(1) over(order by HIRE_DATE_1 range between 1 preceding and 1 preceding) as PREV_MIN_SA
FROM (
    SELECT 
        EMPID,
        NAME,
        (EXTRACT(year from HIRE_DATE)*10000)+(EXTRACT(MONTH FROM HIRE_DATE) * 100) + (extract(DAY from HIRE_DATE)) as HIRE_DATE_1,SALARY
     FROM EMPLOYEE A order by HIRE_DATE,SALARY
) A
ORDER BY HIRE_DATE_1 

Набор результатов:

EMPID   NAME    HIRE_DATE_1 SALARY  PREV_MIN_SA
100     Ravi    20180101    5000    0
101     Kumar   20180101    7000    0
102     Satish  20180101    13000   0
103     Naresh  20180102    7500    3
105     Lalith  20180104    17300   0
104     Suresh  20180104    40000   0
106     Latha   20180201    16000   0

Внутренний запрос просто конвертирует дату в числовой YYYYMMDDформат.Мое намерение состоит в том, чтобы получить количество людей, которые присоединились непосредственно перед датой сотрудника в каждой записи.Я могу взять количество строк с тем же HIRE_DATE и использовать функцию LAG, но как-то не понимаю, как sql возвращает этот набор результатов.

Кроме того, как только я закончу с подсчетами, я хотел бы получить MIN (SALARY) сотрудников, которые присоединились непосредственно к сотруднику в текущем ряду и находят разницу в зарплатах, поэтому мне интересно, могу ли я как-то определить окно, чтобы иметь только все записи с непосредственным предшествующим HIRE_DATE.

Спасибо

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Я полагаю, что это то, что вам нужно (я оставил вам упражнение, чтобы найти разницу между максимальной и минимальной зарплатой!):

WITH employee AS (SELECT 100 empid, 'Ravi' NAME, to_date('01/01/2018', 'dd/mm/yyyy') hire_date, 5000 salary FROM dual UNION ALL
                  SELECT 101 empid, 'Kumar' NAME, to_date('01/01/2018', 'dd/mm/yyyy') hire_date, 7000 salary FROM dual UNION ALL
                  SELECT 102 empid, 'Satish' NAME, to_date('01/01/2018', 'dd/mm/yyyy') hire_date, 13000 salary FROM dual UNION ALL
                  SELECT 103 empid, 'Naresh' NAME, to_date('02/01/2018', 'dd/mm/yyyy') hire_date, 7500 salary FROM dual UNION ALL
                  SELECT 104 empid, 'Lalith' NAME, to_date('04/01/2018', 'dd/mm/yyyy') hire_date, 17300 salary FROM dual UNION ALL
                  SELECT 105 empid, 'Suresh' NAME, to_date('04/01/2018', 'dd/mm/yyyy') hire_date, 40000 salary FROM dual UNION ALL
                  SELECT 106 empid, 'Latha' NAME, to_date('01/02/2018', 'dd/mm/yyyy') hire_date, 16000 salary FROM dual)
SELECT empid,
       NAME,
       hire_date,
       salary,
       COUNT(*) OVER (ORDER BY hire_date RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING) prev_day_hire_count,
       MIN(salary) OVER (ORDER BY hire_date RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING) prev_day_min_sal,
       MAX(salary) OVER (ORDER BY hire_date RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING) prev_day_max_sal
FROM   employee;

     EMPID NAME   HIRE_DATE       SALARY PREV_DAY_HIRE_COUNT PREV_DAY_MIN_SAL PREV_DAY_MAX_SAL
---------- ------ ----------- ---------- ------------------- ---------------- ----------------
       100 Ravi   01/01/2018        5000                   0                  
       101 Kumar  01/01/2018        7000                   0                  
       102 Satish 01/01/2018       13000                   0                  
       103 Naresh 02/01/2018        7500                   3             5000            13000
       104 Lalith 04/01/2018       17300                   0                  
       105 Suresh 04/01/2018       40000                   0                  
       106 Latha  01/02/2018       16000                   0                                
0 голосов
/ 21 ноября 2018

Это должно получить предыдущую дату найма ...

SELECT
    EMPID,NAME, HIRE_DATE, SALARY,
    MAX(HIRE_DATE) OVER (ORDER BY HIRE_DATE
                            RANGE BETWEEN UNBOUNDED PRECEDING
                                      AND INTERVAL '1 DAY' PRECEDING
                        )
                           AS PREV_HIRE_DATE
FROM
    EMPLOYEE

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

SELECT
    *
FROM
(
    SELECT
        EMPID,NAME, HIRE_DATE, SALARY,
        MAX(HIRE_DATE) OVER (ORDER BY HIRE_DATE
                                RANGE BETWEEN UNBOUNDED PRECEDING
                                          AND INTERVAL '1 DAY' PRECEDING
                            )
                               AS PREV_HIRE_DATE
    FROM
        EMPLOYEE
)
    EMPS
LEFT JOIN
(
    SELECT
        HIRE_DATE,
        COUNT(*)     AS COUNT_EMPS,
        MIN(SALARY)  AS MIN_SALARY
    FROM
        EMPLOYEE
    GROUP BY
        HIRE_DATE
)
    PREV_EMPS
        ON PREV_EMPS.HIRE_DATE = EMPS.PREV_HIRE_DATE

РЕДАКТИРОВАТЬ:

Может быть попробовать что-то вроде этого? (мне пора бежать, удачи!)

WITH
  ranked AS
(
    SELECT
      *,
      DENSE_RANK() OVER (ORDER BY HIRE_DATE)   AS HIRE_SEQ_ID
    FROM
      EMPLOYEE
)
SELECT
  *,
  MIN(SALARY) OVER (ORDER BY HIRE_SEQ_ID
                       RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING
                   )
                      AS PREV_MIN_SALARY,
  COUNT(*)    OVER (ORDER BY HIRE_SEQ_ID
                       RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING
                   )
                      AS COUNT_PREV_EMPS
FROM
  ranked
...