Ограничить вывод строки - PullRequest
       20

Ограничить вывод строки

3 голосов
/ 29 декабря 2011

У меня возникли проблемы с определением правильного синтаксиса для того, что мне нужно вывести из моего запроса.

Вот мои данные (нет, это не правильные имена столбцов, я пытаюсь сделать эточитать легче) Фактическая таблица, из которой я берусь, содержит 26 столбцов данных.

employeeNumber - recordNumber - job                - dept - type
 12            - 1            - stapler            - 788  - s
 12            - 6            - paper pusher       - 400  - s
 18            - 2            - phone cleaner      - 600  - p
 18            - 4            - sweeper            - 567  - s
 19            - 0            - typist             - 400  - s
 21            - 0            - mouse ball cleaner - 400  - p

Итак, вот правила выбора:
Если тип P, выберите эту запись
Если сотрудникне имеет P-записи, выберите S
Если у сотрудника есть несколько S-записей, выберите меньший номер записи ИЛИ выберите запись, для которой НЕ установлено значение 400 (строка 400 будет всегда быть большим номером записи)
Если есть только одна S-запись, а Dept равен 400, строка должна быть возвращена

Это то, что в настоящее время работает:

SELECT employeeNumber, recordNumber, job, dept, type
FROM employees
WHERE (type = 'P')
 OR
 (type = 'S'
            AND employeeNumber NOT IN
                (
                  SELECT employeeNumber
                  FROM employees
                  WHERE type = 'P'
                )
)
ORDER BY employeeNumber, recordNumber

И что я ХОЧУ сделать, этопоместите "limit = 1" (или что-то подобное) в конце, чтобы в случае нескольких строк S нижний recordNumber был возвращаемой строкой.

Это набор записей, который должен быть возвращен из приведенных выше данных:

employeeNumber - recordNumber - job                - dept - type
 12            - 1            - stapler            - 788  - s
 18            - 2            - phone cleaner      - 600  - p
 19            - 0            - typist             - 400  - s
 21            - 0            - mouse ball cleaner - 400  - p

Очистить как грязь, верно?

Я продолжаю получать ошибки.Есть ли "простой" способ сделать это, что я просто скучаю?

Спасибо за любую помощь, которую вы можете оказать.

Мишель

Ответы [ 2 ]

1 голос
/ 29 декабря 2011

Я не очень хорошо понял эту часть:

выберите меньший номер записи ИЛИ выберите запись, для которой НЕ установлено 400 (строка 400 всегда будет большим номером записи)

(Если «строка 400 всегда будет с более высоким номером записи», тогда левой части ИЛИ достаточно)

Однако это точка старта. (Я отклонилчасть после ИЛИ)

SELECT * FROM (
    SELECT employeeNumber, recordNumber, job, dept, type
    rank() over (partition by employeeNumber order by type, recordNumber) as rnk
    FROM employees
)
WHERE type = 'P' or (rnk=1 and type=S)
0 голосов
/ 30 декабря 2011

Если ваши данные не могут иметь повторяющиеся значения TYPE и recordNumber внутри employeeNumber, тогда ответ @ Florin сработает. В противном случае, если есть хоть какой-то шанс, что ваш ORDER BY в аналитической функции даст две строки с одинаковым рангом, вы снова получите повторяющиеся строки. Вместо этого я бы использовал ROW_NUMBER, и предложение WHERE можно упростить, чтобы просто выбрать все строки с номером строки 1 (что можно сделать и с помощью запроса @ Florin):

CREATE TABLE employees (employeeNumber INTEGER, recordNumber INTEGER
           , job VARCHAR2(100), dept INTEGER, TYPE VARCHAR2(2));

INSERT INTO employees VALUES (12, 6, 'paper pusher', 400, 'S');
INSERT INTO employees VALUES (18, 2, 'phone cleaner', 600, 'P');
INSERT INTO employees VALUES (18, 4, 'sweeper', 567, 'S');
INSERT INTO employees VALUES (19, 0, 'typist', 400, 'S');
INSERT INTO employees VALUES (21, 0, 'mouse ball cleaner', 400, 'P');
INSERT INTO employees VALUES (12, 1, 'stapler', 788, 'S');
INSERT INTO employees VALUES (12, 1, 'stapler2', 654, 'S');

SELECT employeeNumber, recordNumber, job, dept, type
  FROM (SELECT employeeNumber, recordNumber, job, dept, type
             , ROW_NUMBER() 
                 OVER (PARTITION BY employeeNumber 
                           ORDER BY type, recordNumber) rn
          FROM employees)
 WHERE rn = 1;

Выходит так:

EMPLOYEENUMBER  RECORDNUMBER JOB                   DEPT TYPE
-------------- ------------- -------------------- ----- ----
            12             1 stapler                788 S
            18             2 phone cleaner          600 P
            19             0 typist                 400 S
            21             0 mouse ball cleaner     400 P

Использование RANK с этими данными даст 2 строки для сотрудника 12. Конечно, если этого не произойдет, возможно, вы захотите, чтобы ваш запрос сообщил об этом факте.

...