У меня есть запрос выбора внутри запроса выбора, который выдает ошибку: более одной строки, возвращаемой подзапросом, используемым как выражение

Я пытаюсь отобразить несколько вещей, таких как идентификатор пользователя, зарплата и т. д. Для этого я использовал оператор select. В этом операторе выбора мне нужно использовать другой оператор выбора, чтобы указать «долю зарплаты». Запрос дроби правильный. Когда я пытаюсь использовать этот выбор в основном выборе, он дает ошибку "более одной строки, возвращенной..." Пример данных:

//sample data
insert into employee(id_user int,salary_date date,salary_value) values 
(3, 2017-06-28, 15)
( 5, 2017-06-26 5)
( 2, 2017-06-20 5)
( 1, 2017-06-20 15)
( 4, 2017-06-17 25)

//expected output:
id date       sal  newdate   days aboveavgsal     date     current/firstsal 
1  2017-06-20 15  2017-05-20   31   N           2017-04-20    0.6
1  2017-05-20 10  2017-04-20   30   N           2017-04-20    0.4
1  2017-04-20 20  2017-03-20   31   Y           2017-03-20    0.8
1  2017-03-20 20  2017-02-20   28   Y           NULL          0.8
1  2017-02-20 15  NULL         NULL N           NULL          0.6

    SELECT  id_user
            , salary_date
            , salary_value
            , lead(salary_date) OVER(PARTITION BY id_user ORDER BY salary_date desc)
            , salary_date::timestamp - lead(salary_date::timestamp) over (PARTITION BY id_user ORDER BY salary_date DESC)
            , CASE WHEN salary_value >= 20 THEN 'Y' ELSE 'N' END
            , CASE WHEN salary_value >= 20 THEN lead(salary_date) OVER(PARTITION BY id_user ORDER BY salary_date DESC) END
            , (SELECT CAST(t1.salary_value AS float) / CAST(t.salary_value AS float) 
               FROM (
                     SELECT  t.id_user
                             , t.salary_value
                             , ROW_NUMBER() OVER(PARTITION BY t.id_user ORDER BY t.salary_date) AS rowrank
                     FROM employee t
                    ) AS t
                    INNER JOIN employee AS t1 ON t1.id_user = t.id_user
                    WHERE t.rowrank = 1
                    GROUP BY t1.id_user, t1.salary_value, t1.salary_date, t.salary_value, t.rowrank
                    ORDER BY t1.id_user, t1.salary_date DESC
              ) AS fraction
    FROM employee


Error starts in this query which i tried enclosing in braces.

    (SELECT  CAST(t1.salary_value AS float) / CAST(t.salary_value AS float) 
     FROM (
           SELECT t.id_user
                  , t.salary_value
                  , row_number() OVER(PARTITION BY t.id_user ORDER BY t.salary_date ) AS rowrank
           FROM employee t) AS t
           INNER JOIN employee t1 ON t1.id_user = t.id_user
           WHERE t.rowrank = 1
           GROUP BY t1.id_user, t1.salary_value, t1.salary_date, t.salary_value, t.rowrank
           ORDER BY t1.id_user, t1.salary_date DESC
          )



person Gourishankar Bawade    schedule 27.03.2019    source источник
comment
Попробуйте выполнить отладку, запустив подзапрос независимо, и посмотрите, возвращает ли он более одной строки.   -  person Michael Muryn    schedule 27.03.2019
comment
Кроме того, похоже, что нет никакого условия, связывающего основную таблицу запросов с этим подзапросом, чтобы изолировать одну строку, связанную с этим основным запросом... так что там что-то должно отсутствовать. И есть вероятность, что вы хотите связать этот подзапрос с основным запросом, а не использовать подзапрос.   -  person Michael Muryn    schedule 27.03.2019
comment
Подзапрос возвращает более одной строки, поэтому он не может отображаться в списке SELECT. Может быть, вы можете поместить это в предложение FROM?   -  person Laurenz Albe    schedule 27.03.2019
comment
И это немного субъективно, но для такого более сложного запроса я бы очень хотел написать его более понятным образом, все упаковано вместе. Я сделал это локально, просто чтобы понять, что происходит. Я могу предложить способ написать это после того, как другие вопросы будут прояснены.   -  person Michael Muryn    schedule 27.03.2019
comment
@MichaelMuryn Да, я выполнил запрос отдельно. Это работает нормально. Он возвращает только один столбец с теми же строками, что и другой запрос на выборку.   -  person Gourishankar Bawade    schedule 27.03.2019
comment
@PavelSmirnov Он содержит только зарплату int, идентификатор пользователя int, дату даты; 68 3 28.06.2017 15; 67 5 2017-06-26 5; 66 2 20.06.2017 5;   -  person Gourishankar Bawade    schedule 27.03.2019
comment
Подзапрос должен возвращать более одной строки. Мне нужны эти строки вместе с результатами других строк. Количество строк одинаковое.   -  person Gourishankar Bawade    schedule 27.03.2019
comment
Затем вам нужно переместить этот подзапрос, возможно, как JOIN в основной запрос.   -  person Michael Muryn    schedule 27.03.2019
comment
@LaurenzAlbe да, он возвращает более одной строки. Так что он не может отображаться в списке выбора? Так как же это сделать тогда? Из статьи?   -  person Gourishankar Bawade    schedule 27.03.2019
comment
Я бы предложил предоставить образец данных в форме INSERT INTO TABLE VALUES... Затем предоставить образец ожидаемых результатов. Это поможет нам помочь вам. :)   -  person Michael Muryn    schedule 27.03.2019
comment
Почему этот сотрудник INNER JOIN AS t1 ON t1.id_user = t.id_user ... не существует ТОЛЬКО ОДНОГО сотрудника.id_user в вашей таблице (например, идентификатор уникален или для каждого идентификатора пользователя существует несколько записей сотрудников?)   -  person Michael Muryn    schedule 27.03.2019
comment
@MichaelMuryn Я думал о присоединении ... но в подзапросе уже есть 2 соединения. Я не должен это понимать   -  person Gourishankar Bawade    schedule 27.03.2019
comment
@MichaelMuryn есть несколько записей о зарплате на одного сотрудника. В этом конкретном запросе я объединяю два запроса, чтобы найти долю (current sal/First sal) , поэтому у сотрудников есть несколько изменений заработной платы. Есть 5 сотрудников с многократными изменениями заработной платы   -  person Gourishankar Bawade    schedule 27.03.2019
comment
Если я правильно понимаю, глядя быстро, идея подзапроса состоит в том, чтобы получить первую зарплату пользователя, верно? Чтобы сделать этот знаменитый расчет current_salary / first_salary, верно?   -  person Michael Muryn    schedule 28.03.2019
comment
Вы проверили данные своего примера или они отображают тарабарщину. Например, первая запись для зарплаты (самая низкая дата), я ожидаю, что она будет иметь коэффициент 1, так как она будет делиться сама по себе.   -  person Michael Muryn    schedule 28.03.2019
comment
Можете ли вы добавить столбец идентификатора в эту таблицу, чтобы легко идентифицировать каждую строку по одному полю?   -  person Michael Muryn    schedule 28.03.2019


Ответы (1)


В этой части вашего заявления

(SELECT  CAST(t1.salary_value AS float) / CAST(t.salary_value AS float)

Приведение требует, чтобы t1.salary было единственным значением.

Однако эта часть возвращает более одной строки.

       SELECT t.id_user
              , t.salary_value
              , row_number() OVER(PARTITION BY t.id_user ORDER BY t.salary_date ) AS rowrank
       FROM employee t) AS t
       INNER JOIN employee t1 ON t1.id_user = t.id_user
       WHERE t.rowrank = 1
       GROUP BY t1.id_user, t1.salary_value, t1.salary_date, t.salary_value, t.rowrank
       ORDER BY t1.id_user, t1.salary_date DESC
person cbeckley    schedule 27.03.2019
comment
Я хочу, чтобы он возвращал более одной строки... много строк. Мне придется использовать другое соединение, не так ли? - person Gourishankar Bawade; 27.03.2019
comment
Ах, да, в этом случае вам нужно взять этот подвыбор и превратить его во встроенную таблицу и присоединиться к ней, а затем выполнить свои вычисления. - person cbeckley; 27.03.2019
comment
Но если я создам таблицу и присоединюсь к ней, это повлияет на мои предыдущие запросы в их группах и порядке и многое другое. - person Gourishankar Bawade; 27.03.2019
comment
да, я боюсь, что нет никакого способа обойти это. - person cbeckley; 27.03.2019
comment
1) Скажем, я объединил два запроса, в которых количество строк значительно не увеличилось? 2) Имеет ли значение, если первый запрос возвращает 4 строки, а другой запрос, к которому я собираюсь присоединиться, возвращает 6, имеет ли значение разница? - person Gourishankar Bawade; 27.03.2019