Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.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 两列中数字之间的百分比差异_Sql_Ms Access - Fatal编程技术网

Sql 两列中数字之间的百分比差异

Sql 两列中数字之间的百分比差异,sql,ms-access,Sql,Ms Access,我的SQL经验相当少,所以请在这里对我放松。我有一个表tblForEx,我正在尝试创建一个查询,它查看一个特定的列LastSalesRateChangeDate和ForExRate 基本上,我想做的是让查询检查LastSalesRateChangeDate,然后提取ForExRate列中明显位于同一行的ForExRate,然后我需要检查自上次更改LastSalesRateChangeDate以来是否有+/-5%的更改。我希望这是有道理的,我尽量解释清楚 我相信我需要创建一个“子查询”来查看Las

我的SQL经验相当少,所以请在这里对我放松。我有一个表tblForEx,我正在尝试创建一个查询,它查看一个特定的列LastSalesRateChangeDate和ForExRate

基本上,我想做的是让查询检查LastSalesRateChangeDate,然后提取ForExRate列中明显位于同一行的ForExRate,然后我需要检查自上次更改LastSalesRateChangeDate以来是否有+/-5%的更改。我希望这是有道理的,我尽量解释清楚

我相信我需要创建一个“子查询”来查看LastSalesRateChangeDate,并从该日期提取外汇汇率,但我不知道该怎么做

我应该补充一点,这是在Access SQL中完成的

示例数据,以下是该表的外观:

| BaseCur | ForCur | ForExRate | LastSalesRateChangeDate
| USD     | BRL    | 1.718     | 12/9/2008      
| USD     | BRL    | 1.65      | 11/8/2008
因此,我需要一个查询来查看LastSalesRateChangeDate列,检查日期是否已更改,如果已更改,则获取ForExRate值,然后给出该ForExRate值与上次记录的百分比差

所以最终的结果可能是

"BaseCur" "ForCur" "Percentage Change since Last Sales Rate Change"
USD         BRL            X%

如果我理解正确,您需要前面的值。在MS Access中,可以使用相关子查询:

select t.*,
       (select top (1) t2.LastSalesRateChangeDate
        from tblForEx as t2
        where t2.BaseCur = t.BaseCur and t2.ForCur = t.ForCur
              t2.LastSalesRateChangeDate < t.LastSalesRateChangeDate
        order by t2.LastSalesRateChangeDate desc
       ) as prev_LastSalesRateChangeDate
from t;

根据我的理解,您可以使用LEAD函数通过以下查询在新列中获取上次更改的日期比率:

WITH CTE AS (
SELECT *, LEAD(ForExRate, 1) OVER(PARTITION BY BaseCur, ForCur ORDER BY LastChangeDate DESC) LastValue
FROM #TT
)
SELECT BaseCur, ForCur, ForExRate, LastChangeDate , CAST( ((ForExRate - ISNULL(LastValue, 0))/LastValue)*100 AS float)
FROM CTE
这里的问题是:

对于GROUPBY中的每一行,您将有一个新的计算列,这是我们使用LEAD函数生成的

若一个特定的BaseCur和ForCur只有一行,那个么列中也将有NULL

决议: 如果您确定每个BaseCur和ForCur至少有两行,那么可以使用WHERE子句删除最终结果中的空值

WITH CTE AS (
SELECT *, LEAD(ForExRate, 1) OVER(PARTITION BY BaseCur, ForCur ORDER BY LastChangeDate DESC) LastValue
FROM #TT
)
SELECT BaseCur, ForCur, ForExRate, LastChangeDate , CAST( ((ForExRate - ISNULL(LastValue, 0))/LastValue)*100 AS float) Percentage
FROM CTE
    WHERE LastValue IS NOT NULL
这将使用一系列子查询。首先,您要为BaseCur和ForCur选择最近的日期。然后,您将在前一个日期加入。为此,我使用另一个子查询来选择前两个日期,并排除与先前建立的最近日期相等的日期。这是摘要子查询

然后,在basetbl子查询中获得BaseCur、ForCur、NewDate和OldDate。然后,将原始表的两个简单联接返回到这些日期,以获得当时适用的速率

最后,您要选择BaseCur、ForCur和任何要用于计算速率变化的公式。我用了一个简单的比率,但很容易改变。如果需要,可以删除第一行中的日期,它们仅作为参考点


它看起来并不漂亮,但复杂的Access SQL查询永远不会这样做。

Gordon的答案指向了正确的方向:

SELECT t2.*, (SELECT top 1 t.ForExRate
FROM tblForEx t
where t.BaseCur=t2.BaseCur AND t.ForCur=t2.ForCur and t.LastSalesRateChangeDate<t2.LastSalesRateChangeDate
order by t.LastSalesRateChangeDate DESC, t.ForExRate DESC
) AS PreviousRate, [ForExRate]/[PreviousRate]-1 AS ChangeRatio
FROM tblForEx AS t2;

Access在子查询中的前1个导致连接的地方给出错误。我们打破了联系,因此通过在ORDERBY子句中添加一个额外的项来消除错误。要获得显示为百分比的比率,请切换到“设计”视图,并相应更改该列的属性。

编辑您的问题并提供示例数据和所需结果。。示例数据和预期结果比文本描述有用得多。在我的问题中添加了一些示例数据。2个问题:是1.718/1.65还是1.65/1.78?如果您没有以前的值,您希望返回什么?1.0? 空值?它将是1.65/1.78,如果没有返回值,空值可能是最好的选择。我很感谢你的帮助。Gordon这看起来肯定会满足我的要求,现在子查询对我来说是全新的东西,我是否需要创建底部查询并将其链接到顶部查询?我不确定如何从底部的“联接”查询引用子查询您只需要底部的子查询。顶部嵌入底部。另外,假设我应该用“tblForEx”替换所有的“t”,对吗?我知道t2是临时表啊,我不知道我怎么会没有注意到,底部的表包含了整个查询,现在我只需要确定每个't'是否都需要tblForEx,我想是吗?但是“t2”和它们一样好吗?我试着按原样运行代码,并将“t”改为我的名为tblForEx的表,但我得到了“语法错误”查询表达式中缺少运算符,Access不支持LEAD或LAG函数。当谈到SQL支持时,它有点原始。这在输出表中根本没有给我一个百分比,我得到一个错误框,上面写着“这个子查询最多可以返回一条记录”。嗯,我在本地没有得到。不过,我确实必须将ChangeRatio列的显示格式更改为%。您正在运行哪个版本的MS Access。我在2013年进行了测试。我正在使用2016年的Steve,这可能是问题所在吗?也许吧,但我不明白为什么会有问题。我得做些调查。当然,子查询只意味着每行外部查询返回1条记录 nder如果您的数据中有多条记录具有相同的BaseCur和ForCur组合的相同更改日期,则会出现关联情况?
SELECT basetbl.BaseCur, basetbl.ForCur, basetbl.NewDate, basetbl.OldDate, num2.ForExRate/num1.ForExRate*100 AS PercentChange FROM 
(((SELECT t.BaseCur, t.ForCur, MAX(t.LastSalesRateChangeDate) AS NewDate, summary.Last_Date AS OldDate
FROM (tblForEx AS t 
    LEFT JOIN (SELECT TOP 2 BaseCur, ForCur, MAX(LastSalesRateChangeDate) AS Last_Date FROM tblForEx AS t1 
            WHERE LastSalesRateChangeDate <> 
            (SELECT MAX(LastSalesRateChangeDate) FROM tblForEx t2 WHERE t2.BaseCur = t1.BaseCur AND t2.ForCur = t1.ForCur) 
            GROUP BY BaseCur, ForCur) AS summary 
        ON summary.ForCur = t.ForCur AND summary.BaseCur = t.BaseCur)
GROUP BY t.BaseCur, t.ForCur, summary.Last_Date) basetbl
LEFT JOIN tblForEx num1 ON num1.BaseCur=basetbl.BaseCur AND num1.ForCur = basetbl.ForCur AND num1.LastSalesRateChangeDate = basetbl.OldDate))
LEFT JOIN tblForEx num2 ON num2.BaseCur=basetbl.BaseCur AND num2.ForCur = basetbl.ForCur AND num2.LastSalesRateChangeDate = basetbl.NewDate;
SELECT t2.*, (SELECT top 1 t.ForExRate
FROM tblForEx t
where t.BaseCur=t2.BaseCur AND t.ForCur=t2.ForCur and t.LastSalesRateChangeDate<t2.LastSalesRateChangeDate
order by t.LastSalesRateChangeDate DESC, t.ForExRate DESC
) AS PreviousRate, [ForExRate]/[PreviousRate]-1 AS ChangeRatio
FROM tblForEx AS t2;