【问题标题】:Access 2013 SQL to perform linear interpolation where necessary访问 2013 SQL 以在必要时执行线性插值
【发布时间】:2015-03-18 21:56:48
【问题描述】:

我有一个数据库,其中有 13 种不同的产品,在 6 个不同的国家/地区销售。

价格每年上涨一次。

需要使用线性插值法计算价格。我每年为每个国家/地区的每种产品设置 21 种不同的价格和数量增量。

用户需要能够看到任何给定价值的订单将花费多少(如您所料)。

数据库需要做的(用英文!)是:

如果 TblPrices 中的 TblOrderDetail 存在匹配数量, 使用当前产品、国家和年份的价格

如果没有匹配的数量,但一个产品 (GT) 所需的数量大于 1000,而其他所有产品的数量都大于 100: 找到产品、国家和年份的最高数量(因此,1000 或 100,取决于产品),并计算按比例分配的价格。例如。如果有人想要 2015 年英国的 1500 GT 产品,我们会查看 2015 年英国 1000 GT 的价格并将其乘以 1.5。如果需要 1800,我们会将其乘以 1.8。我还没有能够让这个工作,因为我正在查看它以及下一个可能性的公式......

如果没有匹配的数量,并且产品GT所需的数量小于1000,而其他产品的数量为100(这是常态)... 在用户所需的产品、国家和年份的数量正下方找到增量的数量和价格(我们将这些数量称为以下数量和价格以下)

在用户所需产品、国家和年份所需数量的正上方找到增量的数量和价格(我们称这些数量和价格)

使用此公式计算特定国家/地区的帐户持有人在给定年份所需数量的产品的价格。

ActualPrice: PriceBelow + ((PriceAbove - PriceBelow) * (The quantity required in the order detail - QuantityBelow) / (QuantityAbove - QuantityBelow))

我已经为此花费了数天时间,并且之前曾就此寻求过建议,但我仍然陷入困境。

我一直在尝试使用的表格如下:

TblAccount(主键是 AccountID,它还有一个 Country 字段连接到 TblCountry.Code(主键)

TblOrders(主键是订单 ID)通过 AccountID 字段连接到 TblAccount;通过 OrderID 的 TblOrderDetail。此表还包含与 TblContact 中的人员相关联的 OrderDate 和收件人 ID - 我在这里不需要它,但稍后会需要它来生成发票

TblOrderDetail(主键为 DetailID)通过 OrderID 字段连接到 TblOrders; TblProducts 通过 ProductID 字段,并保存所需的数量以及产品

TblProducts(主键是 ProductCode)除了加入到 TblOrderDetail 之外,还通过 Product 字段加入到 TblPrice

TblPrices 链接到 TblProducts(正如您刚刚阅读的那样)。我还为 TblCountry (CountryAliasForProductCode) 创建了一个别名,因此我可以将其链接到 TblPrices 以显示国家/地区链接。我不确定我是否需要这样做 - 如果我这样做或不这样做都行不通,所以我在这里再次寻求指导。

这是我一直在尝试使用(但失败)的代码,以使我的价格和数量步骤高于我希望复制它,进行一些调整以获得以下步骤:

SELECT MIN(TblPrices.stepquantity) AS QuantityAbove, MIN(TblPrices.StepPrice) AS PriceAbove, TblOrders.OrderID, TblOrders.OldOrderID, TblOrders.AccountID, TblOrders.OrderDate, TblOrders.RecipientID, TblOrders.OrderStatus, TblOrderDetail.DetailID, TblOrderDetail.Product, TblOrderDetail.Quantity

FROM (TblCountry INNER JOIN ((TblAccount INNER JOIN TblOrders ON TblAccount.AccountID = TblOrders.AccountID) INNER JOIN (TblOrderDetail INNER JOIN TblProducts ON TblOrderDetail.Product = TblProducts.ProductCode) ON TblOrders.OrderID = TblOrderDetail.OrderID) ON TblCountry.Code = TblAccount.Country) INNER JOIN (TblCountry AS CountryAliasForProduct INNER JOIN TblPrices ON CountryAliasForProduct.Code = TblPrices.CountryCode) ON TblProducts.ProductCode = TblPrices.Product

WHERE (StepQuantity >= TblOrderDetails.Quantity)
AND (TblPrices.CountryCode = TblAccount.Country)
AND (TblOrderDetail.Product = TblPrices.Product)
AND (DATEPART('yyyy', TblPrices.DateEffective) = DATEPART('yyyy', TblOrders.OrderDate));

我也试过... 我什至尝试回到基础并再次尝试在 1 个查询中生成以下步骤,然后在另一个查询中尝试上述步骤,最后在另一个查询中创建最终计算。

这就是我一直试图让我的价格和数量低于:

SELECT Max(StepQuantity) AS quantity_below, Max(StepPrice) AS price_below, TblOrderDetails.Quantity, TblAccounts.Country
FROM 
(TblProducts INNER JOIN TblPrices ON TblProducts.ProductCode = TblPrices.Product)
(TblOrderDetail INNER JOIN TblProducts ON TblOrderDetail.Product = TblProducts.ProductCode)
(TblOrders INNER JOIN TblOrderDetail ON TblOrders.OrderID = TblOrderDetail.OrderID)
(TblAccount INNER JOIN TblOrders ON TblAccount.AccountID = TblOrders.AccountID),
WHERE (((TblPrices.StepQuantity)<=(TblOrderDetail.Quantity)) AND ((TblPrices.CountryCode)=([TblAccounts].[country])) AND ((TblPrices.Product)=([TblOrderDetail].[product])) AND ((DatePart('yyyy',[TblPrices].[DateApplicable]))=(DatePart('yyyy',[TblOrders].[OrderDate]))));

您可能会在其中看到明显的错误,但恐怕我看不到。我已经尝试重新调整它,但我一无所获。

我需要能够将信息与 OrderDetail 记录联系起来,因为生成的价格需要作为借方金额添加到金融交易表中,并将显示为报表中的欠款金额。

我真的不太擅长 SQL。我已经阅读和工作了几本自学书籍,我以前也问过这个问题的一部分;但我真的很挣扎。如果有人对如何继续有任何想法,或者我的代码哪里出了问题,我会很高兴,即使你告诉我我不应该使用 SQL。作为记录,我最初在 Visual Basic 下的另一个论坛上发布了这个问题。来自那个论坛的回复让我想到了 SQL——但是,任何可行的都很好!

我什至尝试使用 Excel 连接 Year&Product&Country&Quantity 以获得唯一的产品代码,将每个产品、国家和年份的 1 到 1000 之间的每个数量的价格插入 TblProductsAndPrices 表。在 Access 中,我创建了一个查询来连接 Year(of order date from tblOrders)&Product(of tblorderdetails)&Country(of tblAccount),以获取订单所需的产品代码。另一个查询会为我找到一个价格。但是,任何未出现在列表中的产品代码(例如,由于数量大于最高价格增量而未在 tblProductsAndPrices 中列出的数量)都没有价格。

如果我刚才描述的问题有一个可行的解决方案,可以为所有东西产生价格,那我会很高兴。

我真的很希望能够在任何日期为任何国家的任何账户生成任何数量的任何产品的订单,并检索将用于“借记”数据库中金融账户的价格,谁在帐户的交易历史中并出现在报表上。我还希望能够在现场进行临时价格检查。

非常感谢您花时间阅读本文。对此,我真的非常感激。如果您能提供任何帮助或鼓励的话,我将非常感激。

非常感谢 凯伦

【问题讨论】:

  • 请不要用你的名字签字,有必要发这么长的帖子吗?
  • 感谢您的 cmets 以赛亚。我会记住这一点。这是我在这里的第一篇文章。
  • Karen(Isaiah 似乎今天过得很糟糕,抱歉),我通常使用 VBA 来完成此类任务 - 这意味着打开和搜索记录集,如果可能的话查找值,继续下一个任务,等等在。您可以按照您的英语逻辑逐步构建。一系列查询很可能是其中的一部分,但它更容易调试和维护。
  • 谢谢古斯塔夫。没问题。我们都有糟糕的日子!你能指导我找到我可以用来解决这个问题的任何资源吗?我的 VB 和我的 SQL 一样糟糕。干杯。
  • 这么长的问题几乎是不可能阅读的......我想最好的办法是提供数据库的样本副本,或者一次采取一步进行查询...

标签: sql ms-access multiple-tables relationships linear-interpolation


【解决方案1】:

也许没有人想到一个简单的问题解决方案,因为并非所有的头脑都在思考数据库。

简单的解决方案:创建一个提供所有计算值的视图,不仅是您需要的最后一个值,而且每个值都作为一列。然后,您可以在关系视图中使用此类视图,并在某些行上使用其中一个值,在其他行上使用其他值等。

如何思考很简单,以相反的顺序思考,而不是思考“如果那样,那么我需要计算其他我需要这个其他”,而是认为“我需要“这样”并且我需要“这个其他”,两者兼而有之是中间视图的列,然后在顶层考虑“如果”那将是另一个视图,这样的视图将选择正确的值而忽略其余部分。

永远不要尝试一步解决所有问题,这可能会非常令人头疼。

优点:您可以隔离计算值(需要或不需要),sql 更易于编写和维护。

缺点:资源使用量大于最小值,但大多数情况下,额外计算的值并不代表真正的大影响。

就那里的教程而言:使用 Down-Top 方法代替 Top-Down 方法。

有时最好(以您的示例)计算所有三个值(您用粗体写句子)忽略 if 部分,并为您的订单设置所有三个可能的值,然后丢弃不需要的值,而不是尝试只计算一个。

试图只计算一个是程序式编程,在大多数情况下使用数据库时,必须摆脱这种思维并逆向思考,首先做这种程序式编程的最内部部分以收集所有数据,然后做程序编程的外部选择。

注意:如果其中一个值无法计算,只需生成一个 Null。

我知道很难考虑先进后出(Down-Top)模型,但它非常适合您想要的东西。

Step1(在特定视图上,或每次计算从一个视图连接):

  • 将第 1 列计算为 price for the current product, country and year
  • 将第 2 列计算为 calculate a pro-rated price as if 1000
  • 将第 3 列计算为calculate a pro-rated price as if 100
  • 将第 4 列计算为etc
  • 将 N 列计算为etc

第 2 步(另一种视图,您想要的):

  • 计算 if 部分,以便您可以从之前的视图中选择适当的列(您可以立即使用 if 或计算的辅助字段)。

希望你能遵循这些思维方式,我已经解决了很多类似的(和更复杂的)思维方式,但这样想并不容易,需要额外的努力。

【讨论】:

    猜你喜欢
    • 2020-04-22
    • 1970-01-01
    • 2012-01-29
    • 2012-02-08
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    相关资源
    最近更新 更多