SQL Query组合了多个结果或连接表

时间:2015-09-04 03:22:33

标签: sql-server database join sql-server-2012

我有以下表格

  

处置表

  Dis_ID | OfferID  |  RequestID
------------------------------------
 34564   | 123       |    9
 77456   | 123       |    8
 25252   | 124       |    7
 46464   | 125       |    10
 36464   | 125       |    6
 35353   | 125       |    5
  

请求表

  RequestID | AccountNum | 
---------------------------
 5          | 548543      |   
 6          | 548543      |
 7          | 684567      |  
 8          | 684567      |  
 9          | 684567      | 
10          | 548543      | 
11          | 684567      | 
  

排名表

 RankID | OfferId  |  RequestID | Score
-------------------------------------------
 34564   | 123       |    11      |   1
 77456   | 124       |    11      |   2
 25252   | 125       |    11      |   3

使用上面的数据我需要一个查询,其行为如下,给定一个请求号查看排名表中的每个记录,在这个例子中我们有3个(123,124和125)。返回此处已加入帐号的Disposition表中出现次数最少的OfferId。在此示例中,offerId 123对于此帐号出现两次,offerId 124出现一次,offerId 125根本不出现此帐号。所以应该返回offerId 125。除非它们全部相同,否则应始终返回存在于排序表中且在Disposition表中出现次数最少的offerId,然后返回Score字段中具有最低值的offerId。例如,如果在Dispostion表中没有出现offerID,则offerId 123将返回,因为其Score值为1.

  

结果表看起来像这样

| OfferId   | Score | Dis_Occurrences 
---------------------------------------------------------------
| 123       |   1   |   2
| 124       |   2   |   1
| 125       |   3   |   0      <--Return this record

这是我到目前为止所拥有的。

SELECT oRank.OfferId, oRank.Rank_Number, count(oRank.OfferId) AS NumDispositions
From Rank oRank
join Request req
on oRank.RequestId = req.RequestId
join Disposition dis 
on oRank.OfferId = dis.OfferId
where req.Customer_Account_Number = 684567 and req.RequestId = 11 and oRank.OfferId = dis.OfferId
group by oRank.Rank_Number, oRank.OfferId
order by NumDispositions, oRank.Rank_Number
  

我的错误结果表看起来像这样

| OfferId   | Score | Dis_Occurrences 
---------------------------------------------------------------
| 123       |   1   |   2
| 124       |   2   |   1
| 125       |   3   |   3      

它计算offerId出现在处置表

中的总次数

2 个答案:

答案 0 :(得分:1)

编辑 - 根据作者的评论,这是另一个版本:

SQLFiddle中的示例:http://sqlfiddle.com/#!6/d3f99/1/0

with RankReqMap as (
    select rnk.OfferId, rnk.Score, reqAcct.AccountNum, reqReq.RequestID
    from           [Rank]  rnk
         left join Request reqAcct on reqAcct.RequestID = rnk.RequestID
         left join Request reqReq  on reqReq.AccountNum = reqAcct.AccountNum

    where rnk.RequestID = 11 -- Put your RequestId filter here
)
select oRank.OfferId
      ,oRank.Score
      ,count(dis.RequestID) as NumDispositions
from           RankReqMap  oRank
     left join Disposition dis on dis.OfferID   = oRank.OfferId
                              and dis.RequestID = oRank.RequestID
group by oRank.OfferId  , oRank.Score
order by NumDispositions, oRank.Score;

原始帖子

SQLFiddle中的示例:http://sqlfiddle.com/#!6/770a8/1/0

此查询假设您已根据OfferID将处置加入排名,因为示例数据中这些表的RequestID不匹配。您可能需要根据自己的需要进行调整,但下面的查询应该会为您提供您正在寻找的记录:

-- Gather base data
with RankData as (
    select rnk.RankID
          ,rnk.OfferID
          ,rnk.RequestID
          ,rnk.Score
          ,Dis_Occurrences = count(dis.OfferID)
    from           dbo.[Rank]      rnk
         left join dbo.Disposition dis on dis.OfferID   = rnk.OfferId
         left join dbo.Request     req on req.RequestID = rnk.RequestID
    group by rnk.RankID, rnk.OfferID, rnk.RequestID, rnk.Score
)
-- Rank count of Dis_Occurrences, taking lowest score into account as a tie breaker
, DispRanking as (
    select rdt.*, Dis_Rank = row_number() over (order by Dis_Occurrences asc, rdt.Score asc)
    from RankData rdt
)
-- Return only the value with the highest ranking
select * from DispRanking where Dis_Rank = 1

另请注意,如果将第二个CTE转换为裸SELECT并在结尾处删除SELECT语句,则可以查看所有记录以及它们如何通过row_number()函数进行排名:

-- Gather base data
with RankData as (
    select rnk.RankID
          ,rnk.OfferID
          ,rnk.RequestID
          ,rnk.Score
          ,Dis_Occurrences = count(dis.OfferID)
    from          dbo.[Rank]      rnk
        left join dbo.Disposition dis on dis.OfferID   = rnk.OfferId
        left join dbo.Request     req on req.RequestID = rnk.RequestID
    group by rnk.RankID, rnk.OfferID, rnk.RequestID, rnk.Score
)
-- Output all values, with rankings
select rdt.*, Dis_Rank = row_number() over (order by Dis_Occurrences asc, rdt.Score asc)
from RankData rdt
祝你好运!

答案 1 :(得分:0)

我认为您可以使用窗口功能:

;with disp as(select offerid, count(*) as ocount 
              from dispositions group by offerid),
rnk as(select r.offerid, 
              row_number() over(partition by r.requestid 
                                order by isnull(d.ocount, 0), r.score) rn 
       from ranks r
       left join disp d on r.offerid = d.offerid)
select * from rnk where rn = 1