【问题标题】:SQL Query combine multiple results or Join tablesSQL Query 组合多个结果或连接表
【发布时间】:2015-09-04 03:22:32
【问题描述】:

我有以下表格

处置表

  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)。返回此联接帐号的处置表中出现次数最少的 OfferId。在此示例中,此帐号的 offerId 123 出现了两次,offerId 124 出现了一次,而此帐号的 offerId 125 根本不出现。所以应该返回 offerId 125。应始终返回存在于 Rank Table 中且在 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 在 Disposition Table 中出现的总次数

【问题讨论】:

  • Sql server 还是 mysql?
  • @GiorgiNakeuri 我正在使用 MicrosoftSQL。
  • Rank 和 Disposition 表应该如何连接?在您的示例查询中,您通过 RequestID 加入它们,但在您发布的示例数据中,它们之间没有共同的 RequestID。也许您打算改为通过 OfferID 加入?
  • @beercohol 你完全正确我已经更新了我的查询不同的结果但仍然不正确谢谢

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


【解决方案1】:

编辑 - 基于作者的 cmets,这是另一个版本:

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 将 Disposition 加入到 Rank,因为您的示例数据中这些表的 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

祝你好运!

【讨论】:

  • 感谢您的回复!!!你的假设是正确的,offerId 很重要,因为我更新了我的查询。我想我把每个人都弄糊涂了,因为我的第一个查询是如此拙劣。我必须使用提供的 RequestID 这将告诉我从 Rank 表中提取哪些记录。我还必须使用帐号间接查找具有 RequestId 的处置记录列表,这些记录映射回请求表中提供的帐号。我尝试了您的解决方案,但我得到了不正确的结果,它实际上没有在排名表和处置表中找到任何匹配的报价
  • 你能澄清你的源表吗?在您提供的查询中,您引用了 oRank.Rank_Number,它不会出现在您的数据中的任何位置。根据您的数据,我还假设 Request 中的 Customer_Account_Number 应该是 AccountNum ...
  • 做了几个假设并发布了一个更新版本,在顶部显示您的零值。看看那个是否适合你。
  • 令人尴尬的是,在我发帖之前,我被困在这个问题上一个星期,非常感谢一个人!!!。题外话,你有什么推荐的 SQL 资源吗
【解决方案2】:

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

;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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-27
    • 2018-11-02
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 2022-12-22
    相关资源
    最近更新 更多