加入相同的表不会返回预期的结果

时间:2018-03-15 21:49:26

标签: sql sql-server join

我有一个包含字段和数据的表格如下。

appid     determid      empid   empchargeperc 
1          14           79        1.0
1          15           71        0.42
1          16           70        0.04
1          16           71        0.41
1          16           79        0.13

我想要的是基于最后2个确定ID(上表中的15和16)我希望获得所有雇主ID(empids),符合以下3个条件。

  1. 获取旧确定(15)中存在的所有empid,而不是新确定(16)。输出:无
  2. 获取新的确定(16)中存在的所有empid,而不是旧的确定(15)。输出:empids:70,79
  3. 比较旧雇主和新雇主的雇主收费百分比(empchargeperc),如果变更,则退还雇主。如上表所示,对于确定15,只有一个empid 71,因此将其与确定16的empid 71进行比较,并且与0.42>相比较。 0.41,该雇主也将被退回。
  4. 所以我想返回70,71,79。我写下面的查询,我得到预期的输出。

    SELECT DISTINCT a.appid, a.empid
    FROM dbo.emp a JOIN dbo.emp b ON b.appid= a.appid
    WHERE a.determid IN (SELECT TOP(2) determid FROM dbo.determ 
    WHERE appid = @appid ORDER BY createdate DESC) AND 
    a.empchargeperc <> b.empchargeperc
    

    但下表不正确输出。我得到的Empids是47和81,但我预计不应该返回empid,因为确定30,empid 47的empchargeperc匹配确定45的empid 47的empchargeperc。对于empid 81也是如此。

    appid     determid      empid   empchargeperc 
    1          11           47        0.16
    1          11           81        0.83
    1          30           47        0.16
    1          30           81        0.83
    1          45           47        0.16
    1          45           81        0.83
    

    任何帮助都会非常感激。

2 个答案:

答案 0 :(得分:1)

根据您的条件描述,这听起来像是使用having子句聚合:

select empid
from (select d.*, dense_rank() over (order by determid desc) as rnk
      from determ d
     ) d
where rnk <= 2
group by empid
having min(determid) = max(determid) or
       min(empchargeperc) <> max(empchargeperc);

答案 1 :(得分:1)

你可以用CTE清楚地做复杂的事情 - 下面我用这个技术做了第1步和第2步

WITH NEW_D AS
(
  SELECT MAX(determid) as determnd
  FROM dbo.determ 
  WHERE appid = @appid
), OLD_D AS
(
  SELECT MAX(determid) as determid
  FROM dbo.determ, NEW_D
  WHERE appid = @appid AND determid <> NEW_D.determid
), EMP_NEW AS
(
  SELECT empid
  FROM emp, NEW_D
  WHERE appid = @appid AND determid = NEW_D.determid 
), EMP_OLD AS
(
  SELECT empid
  FROM emp, OLD_D
  WHERE appid = @appid AND determid = OLD_D.determid 
)
SELECT empid
FROM EMP_OLD
WHERE empid NOT IN (SELECT empid FROM EMP_NEW)

UNION ALL

SELECT empid
FROM EMP_NEW
WHERE empid NOT IN (SELECT empid FROM EMP_OLD)