在SQL中选择基于另一个字段具有该记录的最小值的记录

时间:2012-06-06 04:03:17

标签: sql

我有一组数据,虽然它加入的字段和表的数量非常复杂,但我相信我可以使用此处所需的字段/表来提炼我的问题,以便说明这个特定问题。

我有三个表:ClientData,Sources,Price

以下是我在选择最小值之前的当前查询:

select c.RecordID, c.Description, s.Source, p.Price, p.Type, p.Weight
from ClientData c
inner join Sources s ON c.RecordID = s.RecordID
inner join Prices p ON s.SourceID = p.SourceID

这会产生以下结果:

RecordID   Description        Source     Price  Type   Weight
=============================================================
001002003  ABC Common Stock   Vendor 1  104.5   Close  1
001002003  ABC Common Stock   Vendor 1  103     Bid    2
001002003  ABC Common Stock   Vendor 2  106     Close  1
001002003  ABC Common Stock   Vendor 2  100     Unknwn 0
111222333  DEF Preferred Stk  Vendor 3  80      Bid    2
111222333  DEF Preferred Stk  Vendor 3  82      Mid    3
111222333  DEF Preferred Stk  Vendor 2  81      Ask    4

我要做的是显示属于同一记录的价格,该记录具有该记录的最小非零权重(因此权重必须大于0,但它必须是剩余的最小值权重)。所以在上面的例子中,对于记录001002003,我想显示供应商1和供应商2的收盘价,因为它们的权重均为1(该记录的最小权重)。但对于111222333,我想仅显示供应商3的出价,因为它的权重为2,该记录的最小值为非零。我想要的结果是:

RecordID   Description        Source     Price  Type   Weight
=============================================================
001002003  ABC Common Stock   Vendor 1  104.5   Close  1
001002003  ABC Common Stock   Vendor 2  106     Close  1
111222333  DEF Preferred Stk  Vendor 3  80      Bid    2

关于如何实现这一目标的任何想法?

编辑:这适用于SQL Server Compact Edition。

3 个答案:

答案 0 :(得分:2)

我能够提出解决方案,所以我想我会分享它:

SELECT x.RecordID, VendorSource, VendorPrice
FROM ClientData x
INNER JOIN Sources s ON x.RecordID = s.RecordID
INNER JOIN Prices p ON s.SourceID = p.SourceID
INNER JOIN (SELECT c.RecordID, MIN(Weight) min_weight
            FROM ClientData c
            INNER JOIN Sources s ON c.RecordID = s.RecordID
            INNER JOIN Prices p ON s.SourceID = p.SourceID
            WHERE Weight != 0 
            GROUP BY c.RecordID) w ON x.RecordID = w.RecordID
WHERE p.Weight = w.min_weight

这允许在派生表中的RecordID级别上填充最小权重,因此每个RecordID有1个权重。

对于所有给出答案的人,谢谢;我感谢您提供的帮助和任何指导。

答案 1 :(得分:0)

我认为你需要稍微改变你的结构,以便按照你的意愿实现这项工作。基本上你有它的方式是一个价格记录是针对Source设置的,而不是针对似乎在ClientData表中的Item。通过从Sources表中删除c.Record数字列并将其放入Price表中,您应该获得正确的One(ClientData)到许多(价格),以及One(ClientData)到许多(Sources)关系,我认为您需要

select c.RecordID, c.Description, s.Source, p.Price, p.Type, p.Weight
from ClientData c
inner join Prices p ON c.RecordID = p.RecordID
inner join Sources s ON s.SourceID = p.SourceID
   AND p.Weight> 0
LEFT OUTER JOIN #Prices p2 ON c.RecordID = p2.RecordID
   AND p2.PriceID <> p.priceID
   AND p2.Weight > 0
   AND p2.Weight < p.Weight
WHERE p2.SourceID IS NULL

如果您进行了上述指定的更改,则此查询将返回您要查找的确切数据。

答案 2 :(得分:0)

您可以将RANK()与RecordId上的分区一起使用,增加权重以“评定”每一行(在完全排除零权重之后),然后简单地过滤掉排名最高的行。 CTE仅用于保持第二个查询简单明了

;WITH MyRecords AS
(
    -- Your source query goes here
    select c.RecordID, c.Description, s.Source, p.Price, p.Type, p.Weight
    from ClientData c
    inner join Sources s ON c.RecordID = s.RecordID
    inner join Prices p ON s.SourceID = p.SourceID
)
SELECT RecordID, [Description], [Source], [Price], [Type], [Weight]
FROM
(
    SELECT RecordID, [Description], [Source], [Price], [Type], [Weight], 
           -- With ranking, the lower the weight the better
           Rnk = RANK() OVER (PARTITION BY RecordId ORDER BY [Weight] ASC)
    FROM MyRecords
    -- But exclude Weight 0 entirely
    WHERE [Weight] > 0
) RankedRecords
-- We just want the top ranked records, with ties
WHERE Rnk = 1
帖子后添加了

编辑 CE约束。请参阅How would I duplicate the Rank function in a Sql Server Compact Edition SELECT statement?,了解如何在CE中模拟RANK()。