Что не так в этом предложении SQL? - PullRequest
1 голос
/ 27 февраля 2010

Вот мое выбранное утверждение,

SELECT TOP 1
  EmpId, RemainingAdvance 
FROM SalaryDetails
WHERE EmpId IN (SELECT Emp_Id
                FROM Employee
                WHERE Desig_Id='27')
ORDER BY CreatedDate DESC

Когда я выполнил SELECT Emp_Id FROM Employee WHERE Desig_Id='27' результаты были

Emp_Id
16
17

Но когда я выполняю свое первое утверждение, оно дает мне результат только для 16, но без вывода 17 ... У меня есть записи для обоих EmpId в SalaryDetails Таблице .....

EDIT:

Удаление TOP 1 из моего запроса, я получил это,

SELECT EmpId, RemainingAdvance FROM SalaryDetails 
where EmpId in (select Emp_Id from Employee where Desig_Id='27')
               ORDER BY CreatedDate DESC 

дал мне

alt text

Я хочу получить результаты для EmpId 16,17 ORDER BY CreatedDate DESC ... Потому что мой теперь мой Desig_Id='27', и я изменит его с переменной @CategoryId ... Так что может быть 'n' количество сотрудников на основе @CategoryId

EmpId  RemainingAdvance
16                354.00
17                 0.00

Ответы [ 6 ]

5 голосов
/ 27 февраля 2010
SELECT SD.EmpId, SD.RemainingAdvance 
FROM 
SalaryDetails SD INNER JOIN 
   (SELECT SD2.EmpID, MAX(SD2.CreatedDate) AS MAXDate 
   FROM SalaryDetails SD2 GROUP BY SD2.EmpID) AS SD2
ON SD.EmpID = SD2.EmpID
INNER JOIN Employee E
ON SD.EmpID = E.EmpID
WHERE E.Desig_Id = '27' AND SD.CreatedDate = SD2.MaxDate

Примечание. Запрос пишется без его проверки.
Я полагаю, это то, что вы ищете.


Этот вариант также работает (по крайней мере, в одной СУБД, а именно в IBM Informix Dynamic Server 11.50):

SELECT SD.EmpId, SD.RemainingAdvance 
  FROM SalaryDetails SD
       INNER JOIN 
       (SELECT SD2.EmpID, MAX(SD2.CreatedDate) AS MAXDate 
          FROM SalaryDetails SD2 GROUP BY SD2.EmpID) AS SD2
       ON SD.EmpID = SD2.EmpID AND SD.CreatedDate = SD2.MaxDate
       INNER JOIN Employee E
       ON SD.EmpID = E.EmpID
 WHERE E.Desig_Id = '27'

Составное объединение в первом предложении ON может повысить производительность запроса, но вполне возможно, что оптимизатор в любом случае поднимет условие 'AND SD.CreatedDate = SD2.MaxDate', то есть вы не заметите никаких разница, даже если вы изучили два плана запроса. Я не совсем уверен, как лучше сделать отступ для табличных выражений после основного предложения FROM.

Под редакцией Джонатана Леффлера - по просьбе Шахкальпеша.

5 голосов
/ 27 февраля 2010

SQL Server 2005+, с использованием CTE и ROW_NUMBER:


WITH summary AS (
    SELECT sd.empid,
           sd.remainingadvance,
           ROW_NUMBER() OVER (PARTITION BY sd.empid ORDER BY sd.createddate DESC) AS rank
      FROM SALARYDETAILS sd
      JOIN EMPLOYEE e ON e.emp_id = sd.empid
                     AND e.desig_id = '27')
SELECT s.empid,
       s.remainingadvance
  FROM summary s
 WHERE s.rank = 1

SQL Server 2005+, не эквивалентный CTE


SELECT s.empid,
       s.remainingadvance
  FROM (SELECT sd.empid,
               sd.remainingadvance,
               ROW_NUMBER() OVER (PARTITION BY sd.empid ORDER BY sd.createddate DESC) AS rank
          FROM SALARYDETAILS sd
          JOIN EMPLOYEE e ON e.emp_id = sd.empid
                         AND e.desig_id = '27') s
 WHERE s.rank = 1

Справка:

5 голосов
/ 27 февраля 2010

SELECT TOP 1 возвращает только одну строку.

Вместо этого можно попробовать SELECT TOP 10.

EDIT

Вы всегда получаете 16, потому что, кажется, оно имеет более высокое значение CreatedDate, и вы сортируете по этому столбцу по убыванию.

3 голосов
/ 27 февраля 2010

Это работает, но коррелированный подзапрос не эффективен:

CREATE TABLE employee
(
    empid INTEGER NOT NULL PRIMARY KEY,
    desig_id CHAR(2) NOT NULL
);

INSERT INTO employee VALUES(16, '27');
INSERT INTO employee VALUES(17, '27');
INSERT INTO employee VALUES(15, '13');
INSERT INTO employee VALUES(18, '9');

CREATE TABLE salarydetails
(
    empid INTEGER NOT NULL REFERENCES employee,
    createdate DATE NOT NULL,
    PRIMARY KEY (empid, createdate),
    remainingAdvance DECIMAL(10,2) NOT NULL
);

INSERT INTO salarydetails VALUES (15, '2009-12-13', 1534.00);
INSERT INTO salarydetails VALUES (16, '2010-01-31', 3634.00);
INSERT INTO salarydetails VALUES (16, '2010-02-14', 2634.00);
INSERT INTO salarydetails VALUES (17, '2010-01-03', 5734.00);
INSERT INTO salarydetails VALUES (17, '2010-02-03', 4734.00);
INSERT INTO salarydetails VALUES (17, '2010-03-01', 3734.00);
INSERT INTO salarydetails VALUES (18, '2010-01-13', 5834.00);

SELECT s1.empid, s1.remainingAdvance
FROM SalaryDetails AS s1
WHERE s1.empid IN (SELECT e.empid FROM employee AS e WHERE e.desig_id = '27')
  AND s1.createdate = (SELECT MAX(s2.createdate)
                          FROM salarydetails AS s2
                         WHERE s2.empid = s1.empid);

Результат:

EmpID       RemainingAdvance
   16                2634.00
   17                3734.00
0 голосов
/ 27 февраля 2010

Оператор работает так, как вам говорят, но не так, как вы намеревались.

Полагаю, вы хотите иметь самую последнюю запись SalaryDetails для каждого сотрудника с определенным Desig_ID:

SELECT EmpId, RemainingAdvance
FROM SalaryDetails
WHERE CreatedDate IN
    (SELECT MAX(d.CreatedDate)
     FROM SalaryDetails d
     INNER JOIN Employee e ON d.EmpId = e.EmpId
     WHERE e.Desig_Id = '27'
     AND SalaryDetails.EmpId = d.EmpId
    )
0 голосов
/ 27 февраля 2010

Выберите Top 1 выберет один верхний ряд. Потеряй верхнюю 1, если хочешь увидеть их все

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