Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server为查询中的每一行计算一个变量_Sql_Sql Server 2008_Variables_Local Variables - Fatal编程技术网

SQL Server为查询中的每一行计算一个变量

SQL Server为查询中的每一行计算一个变量,sql,sql-server-2008,variables,local-variables,Sql,Sql Server 2008,Variables,Local Variables,我有一个包含发票的大型数据集,需要对其执行一些货币转换。获取数据需要很多联接,但基本思想是,一个表有以美元表示的单独发票费用,而另一个表有以当地货币表示的总费用,但没有以当地货币提供的发票上的单独费用,所以我需要计算有效汇率,用当地货币总额除以美元总额,然后用这个汇率乘以费用。到目前为止,我已经成功地完成了一项记录,如下所示: DECLARE @USD_Total float, @LOC_Total float, @FX_Rate float SET @USD_Total = (Select

我有一个包含发票的大型数据集,需要对其执行一些货币转换。获取数据需要很多联接,但基本思想是,一个表有以美元表示的单独发票费用,而另一个表有以当地货币表示的总费用,但没有以当地货币提供的发票上的单独费用,所以我需要计算有效汇率,用当地货币总额除以美元总额,然后用这个汇率乘以费用。到目前为止,我已经成功地完成了一项记录,如下所示:

DECLARE @USD_Total float, @LOC_Total float, @FX_Rate float

SET @USD_Total = (Select SUM (InvoiceTable.USD_ChargeAmount)
FROM 
{Some Joins}
WHERE InvoiceID in ('1234567')
Group By InvoiceTable.InvoiceID)

SET @LOC_Total = (Select LocalInvoiceTable.ChargeTotal
FROM
{Some Joins}
WHERE InvoiceID in ('1234567')
Group By LocalInvoiceTable.InvoiceID

SET @FX_Rate = @LOC_Total / @USD_Total

SELECT
InvoiceTable.InvoiceID
    SUM(CASE InvoiceTable.ChargeCode when 'TYPE A' THEN InvoiceTable.USD_ChargeAmount ELSE 0 END)*@FX_Rate As Type_A,
    SUM(CASE InvoiceTable.ChargeCode when 'TYPE B' THEN InvoiceTable.USD_ChargeAmount ELSE 0 END)*@FX_Rate As Type_B,
    SUM(CASE InvoiceTable.ChargeCode when 'TYPE C' THEN InvoiceTable.USD_ChargeAmount ELSE 0 END)*@FX_Rate As Type_C
FROM
{Some Joins}
WHERE InvoiceID in ('1234567')
Group By LocalInvoiceTable.InvoiceID
所以这很好,但我需要复制数千个发票ID。如果没有WHERE子句,我如何实现这一点?我是这方面的新手,因此非常感谢您的帮助。我正在使用Microsoft SQL Server 2008。

是的,您可以。不,你不应该

这只是一个糟糕的编程实践。为了便于将来的维护,您应该分离和隔离程序的不同部分,想想下一个程序员吧

SQL是一种数据持久性语言,它不是一种伟大的过程语言

无论如何都要使用SQL为报表等选择复杂的数据表示形式,但这里您拥有的是嵌入到数据请求中的业务规则逻辑。这些商业规则在哪里重复

业务规则应该只存在于一个地方,并从那里引用。如果您将业务规则分散在整个系统中,它将很快变得无法维护。历史一再证明了这一点


使用您选择的服务客户机语言Java、c等。任何合适的OO语言都可以完成此任务。对于每个数据集,一次跨所有发票编号进行选择。将整个事务包装在显式事务中,以便在需要时确保稳定的结果

不要考虑单个行。你有一组行,所以要根据每个问题的集合来思考。使用CTE,您可以封装问题每个部分的每个结果集,并在其他CTE或最终查询中组合答案

以下对查询的修改显示了3个CTE:

首先,我们得到每个InvoiceID的美元值 其次,我们得到每个InvoiceID的本地化值 第三,我们根据前两个聚合计算有效汇率,并将其加入各自的发票ID 最后,在主查询中,我们使用有效汇率计算的结果

;WITH USD AS (
    SELECT InvoiceID, SUM(InvoiceTable.USD_ChargeAmount) AS [Total]
    FROM 
    {Some Joins}
    GROUP BY InvoiceTable.InvoiceID
),
LOC AS (
    SELECT InvoiceID, SUM(LocalInvoiceTable.ChargeTotal) AS [Total]
    FROM
    {Some Joins}
    GROUP BY LocalInvoiceTable.InvoiceID
),
FX AS (
    SELECT USD.InvoiceID,
           CONVERT(MONEY, LOC.Total) / CONVERT(MONEY, USD.Total) AS [Rate]
    FROM USD
    INNER JOIN LOC
            ON LOC.InvoiceID = USD.InvoiceID
),
SELECT InvoiceTable.InvoiceID,
       SUM(CASE InvoiceTable.ChargeCode
              when 'TYPE A' THEN InvoiceTable.USD_ChargeAmount
              ELSE 0 END) * FX.[Rate] AS [Type_A],
       SUM(CASE InvoiceTable.ChargeCode
              when 'TYPE B' THEN InvoiceTable.USD_ChargeAmount
              ELSE 0 END) * FX.[Rate] AS [Type_B],
       SUM(CASE InvoiceTable.ChargeCode
              when 'TYPE C' THEN InvoiceTable.USD_ChargeAmount
              ELSE 0 END) * FX.[Rate] AS [Type_C]
FROM InvoiceTable
{Some Joins}
INNER JOIN FX
        ON FX.InvoiceID = InvoiceTable.InvoiceID
编辑: 更理想的方法是存储插入InvoiceTable和LocalInvoiceTable行时使用的汇率。您可以使用类似以下内容的表格:

InvoiceInfo
(
  InvoiceID INT NOT NULL, -- PK, FK to InvoiceTable
  ExchangeRate SMALLMONEY NOT NULL,
  CurrencyCode CHAR(3) NOT NULL, -- USD, EUR, etc.
  InvoiceTotalUSD MONEY, -- optional
  InvoiceTotalLocal MONEY -- optional
)
我建议使用货币代码。这两个InvoiceTotal*字段仅适用于除计算有效汇率外,您通常需要按InvoiceID进行聚合的情况

在创建发票时存储信息可将您的查询简化为:

SELECT InvoiceTable.InvoiceID,
       SUM(CASE InvoiceTable.ChargeCode
              when 'TYPE A' THEN InvoiceTable.USD_ChargeAmount
              ELSE 0 END) * II.[ExchangeRate] AS [Type_A],
       SUM(CASE InvoiceTable.ChargeCode
              when 'TYPE B' THEN InvoiceTable.USD_ChargeAmount
              ELSE 0 END) * II.[ExchangeRate] AS [Type_B],
       SUM(CASE InvoiceTable.ChargeCode
              when 'TYPE C' THEN InvoiceTable.USD_ChargeAmount
              ELSE 0 END) * II.[ExchangeRate] AS [Type_C]
FROM InvoiceTable
{Some Joins}
INNER JOIN InvoiceInfo II
        ON II.InvoiceID = InvoiceTable.InvoiceID

你不能把它当作一个程序性的程序。SQL是一种用于集合操作的语言。您需要考虑计算列和联接之类的术语。首先,您需要根据发票计算美元总额,然后将其加入LocalInvoiceTable,然后除以ChargeTotal得到外汇汇率。最后,返回InvoiceTable并将每个费用乘以汇率

with UsdTotal as
(
  select InvoiceID, sum(USD_ChargeAmount) as USD_ChargeTotal
  from InvoiceTable
  group by InvoiceID
)
, FxRate as
(
  select lit.InvoiceID, lit.ChargeTotal / ut.USD_ChargeTotal as Rate
  from LocalInvoiceTable lit
  inner join UsdTotal ut
    on ut.InvoiceID = lit.InvoiceID
)
select
  it.InvoiceId,
  it.USD_ChargeAmount as UsdValue,
  it.USD_ChargeAmount * fx.Rate as LocalCcyValue
from InvoiceTable it
inner join FxRate fx on fx.InvoiceID = it.InvoiceID

你可以试穿一下。请注意,外汇汇率每天都在变化。如果在不同的日期实现了单独的费用,则无法获得平均的有效汇率。因此,以当地货币计算的金额将与实际金额不同。

感谢srutzky和TomT!这很有魅力,我也很欣赏关于SQL的见解。我是新手,所以你和其他人在这个论坛上的指导是非常宝贵的。