这个sql select语句有什么问题?

时间:2010-02-27 05:45:57

标签: sql sql-server sql-server-2005 tsql

这是我的选择声明,

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 ... 我在SalaryDetails表.....中有两个EmpId的记录。

修改

从我的查询中删除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 http://img189.imageshack.us/img189/6836/resultpane1.jpg

我想要EmpId 16,17 ORDER BY CreatedDate DESC的结果...因为我现在的Desig_Id='27'和我将使用变量@CategoryId进行更改...所以可能会有' n'基于@CategoryId

的员工人数
EmpId  RemainingAdvance
16                354.00
17                 0.00

6 个答案:

答案 0 :(得分:5)

SELECT TOP 1只返回一行。

您可以尝试使用SELECT TOP 10

修改

您总是得到16,因为它似乎有更高的CreatedDate,并且您按该列降序排序。

答案 1 :(得分:5)

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

参考:

答案 2 :(得分:5)

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

注意:查询是在没有尝试的情况下编写的 我想,这就是你要找的东西。


此变体也有效(至少在一个DBMS中 - 即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子句之后缩进表表达式的最佳方法。

由Jonathan Leffler编辑 - 按照Shahkalpesh的要求。

答案 3 :(得分:3)

这样可行,但相关的子查询效率不高:

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

答案 4 :(得分:0)

选择Top 1将选择一个顶行。如果你想看到所有这些,就会失去前1名

答案 5 :(得分:0)

该声明按照告诉您的方式执行,但不是按照您的意图执行。

我想你想拥有一个具有特定Desig_ID的每个员工的最新SalaryDetails记录:

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
    )