当其中一个字段为空但您需要值时,查找最近的数字

时间:2016-05-26 17:50:47

标签: sql sql-server sql-server-2008

我正在制作一份报告,根据GenAmps和GenVolts为我提供每个发电机的月费率。如果我的定价表具有GenAmps#和GenVolt大小,那么它将填充每月费率。如果在我的定价表中找不到GenAmps#和GenVolts值,有些情况可以在下面看到。当发生这种情况时,我希望MonthlyRate从最接近的GenAmps#拉出,其中GenVolts值相等,ex( GenAmps 15, GenVolts KW),这在定价表中找不到,所以我希望它从( GenAmps 20, GenVolts KW)中提取MonthlyRate

GenAmps GenVolts    PricingGenAmp   PricingGenVolt  MonthRate(160hr)
10       KW           NULL              NULL           NULL
15       KVA          NULL              NULL           NULL

如果他们在定价表中找不到GenAmps#和GenVolts值,那么这就是我的报告。

GenAmps GenVolts    MonthRate(160hr)
  25      KVA         1251
  20      KW          1251

(见上图来自定价表)。由于这些不在定价表中,我希望10KW从20KW拉出月率,从25KVA拉出15KVA。所以它看起来像这样:

GenAmps GenVolts    PricingGenAmp   PricingGenVolt  MonthRate(160hr)
10       KW           20                KW              1251
15       KVA          25                KVA             1251

当查询正常工作时,它应该看起来像上面的数据。

GenAmps#的范围是10 - 900,在定价表中找不到。

这是我目前拥有的查询,需要进行修改,以便我可以按照我希望的方式查看数据。

SELECT        TOP (100) PERCENT ContractID, SaleRep, GenAmps, GenVolts, GenPhase, EstRunningHours, MonthlyRate, DeliveryRate, PickupRate, FuelRate, DropCharge, HourlyServiceRate, 
                         CASE WHEN gr.PricingGenAmps IS NULL THEN
                             (SELECT        MAX(GenAmps) AS a1
                               FROM            dbo.GeneratorSizePrices AS a
                               WHERE        (GenAmps < gr.GenAmps) AND a.GenVolts = gr.GenVolts) ELSE gr.PricingGenAmps END AS PricingGenAmp, ISNULL([MonthRate(160hr)],
                             (SELECT        [MonthRate(160hr)]
                               FROM            dbo.GeneratorSizePrices AS b
                               WHERE        (GenAmps =
                                                             (SELECT        MAX(GenAmps) AS a
                                                               FROM            dbo.GeneratorSizePrices
                                                               WHERE        (GenAmps < gr.GenAmps) AND (GenVolts = gr.GenVolts))))) AS Month
FROM            dbo.Elliott_GensRentalRate AS gr
GROUP BY ContractID, SaleRep, GenAmps, GenVolts, GenPhase, EstRunningHours, MonthlyRate, DeliveryRate, PickupRate, FuelRate, DropCharge, HourlyServiceRate, PricingGenAmps, [MonthRate(160hr)]
ORDER BY PricingGenAmps, GenAmps

2 个答案:

答案 0 :(得分:1)

我不确定在查询的其余部分中发生了什么。但是问题的一部分涉及将行与另一个表中最近的行匹配,可以通过这种方式处理。

select *
from
    dbo.Elliott_GensRentalRate as gr cross apply
    (
        select gsp.*, row_number() over
            (order by abs(gr.GenAmps - gsp.GenAmps), sign(gr.GenAmps - gsp.GenAmps)) as rnk
        from dbo.GeneratorSizePrices as gsp
        where gsp.GenVolts = gr.GenVolts
) as gspr /* GeneratorSizePricesRanked */
where gspr.rnk = 1

cross apply可让我们查看查询外的GenAmps表格中gr的值。当cross apply不可用时,还有其他方法可以实现此目的,但这可能更有效。接下来的关键是将潜在的匹配按差异的绝对值排序,然后只保留最高的那个。

由于你应该处理关系,我使用sign()函数来确定更高或更低的匹配是否是首选匹配。如上所述,它有利于四舍五入。如果出于某种原因可能根本找不到匹配项,也可以使用outer apply

答案 1 :(得分:0)

这应该让你开始。没有所有数据,很难确定。干杯!

IF OBJECT_ID('tempdb..#gens') IS NOT NULL DROP TABLE #gens
IF OBJECT_ID('tempdb..#genPrice') IS NOT NULL DROP TABLE #genPrice

CREATE TABLE #gens(
    GenAmps INT,
    GenVolts VARCHAR (3),
    PricingGenAmp INT null,
    PricingGenVolt VARCHAR (3) null,
    MonthRate DECIMAL (6,2) null)

CREATE TABLE #genPrice(
    GenAmps INT,
    GenVolts VARCHAR (3),
    MonthRate DECIMAL (6,2))

INSERT INTO #gens
VALUES(10,'KW',null,null,null),(15,'KVA',null,null,null)

INSERT INTO #genPrice
VALUES(25,'KVA',1251.00),(20,'KW',1151.00)



SELECT
    g.GenAmps,
    g.GenVolts,
    ISNULL(g.PricingGenAmp,(SELECT MIN(gp.GenAmps) FROM #genPrice gp WHERE g.GenVolts = gp.GenVolts and gp.GenAmps > g.GenAmps)) AS PricingGenAmp,
    ISNULL(g.PricingGenVolt,(SELECT GenVolts FROM #genPrice gp2 WHERE gp2.GenAmps = (SELECT MIN(gp.GenAmps) FROM #genPrice gp WHERE g.GenVolts = gp.GenVolts and gp.GenAmps > g.GenAmps))) as PricingGenVolt,
    ISNULL(g.MonthRate,(SELECT MonthRate FROM #genPrice gp3 WHERE gp3.GenAmps = (SELECT MIN(gp.GenAmps) FROM #genPrice gp WHERE g.GenVolts = gp.GenVolts and gp.GenAmps > g.GenAmps))) as MonthRate
FROM
    #gens g