如何比较SQL Server中的前两行

如何比较SQL Server中的前两行,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有以下表格作为示例: MTRL表 |MTRL| CODE | --------------- | 1 | 080109 | | 2 | 085145 | | 3 | 084141 | MTRLINES表 |MTRL| PRICE | FINDOC | ------------------------- | 1 | 4.95 | 12345 | | 1 | 4.50 | 23421 | | 1 | 3.90 | 23499 | |MTRL| P

我有以下表格作为示例:

MTRL表

|MTRL|  CODE  |
---------------
| 1  | 080109 |
| 2  | 085145 |
| 3  | 084141 |
MTRLINES表

|MTRL|  PRICE  | FINDOC |
-------------------------
| 1  |  4.95   | 12345  |
| 1  |  4.50   | 23421  |
| 1  |  3.90   | 23499  |


|MTRL|  PRICE  | FINDOC |
-------------------------
| 2  |  2.95   | 45345  |
我目前正在使用这两个查询,然后将输出存储到一个变量中。我正在和编程做比较但与其运行两个查询,不如运行一个查询,然后获取输出。

所以我想比较一下最后两个价格。如果上一个价格发生了重大变化,或者只有一个价格如mtrl2,则输出价格为1

SELECT 
      , SUB.PRICE
FROM (
        SELECT 
              , ML.PRICE
              , rn = row_number() over (PARTITION BY M.CODE ORDER BY FINDOC DESC)
        FROM  MTRLINES ML
              INNER JOIN MTRL M
                    ON M.MTRL = ML.MTRL  AND FINDOC IN (SELECT FINDOC FROM FINDOC WHERE SOSOURCE=1251 AND FPRMS IN (1,2)) 
              WHERE  M.SODTYPE=51 AND M.COMPANY=1 AND M.CODE=:kod_an
      ) sub
WHERE rn IN (1)
这存储在变量
price1

SELECT 
      , SUB.PRICE
FROM (
        SELECT 
              , ML.PRICE
              , rn = row_number() over (PARTITION BY M.CODE ORDER BY FINDOC DESC)
        FROM  MTRLINES ML
              INNER JOIN MTRL M
                    ON M.MTRL = ML.MTRL  AND FINDOC IN (SELECT FINDOC FROM FINDOC WHERE SOSOURCE=1251 AND FPRMS IN (1,2)) 
              WHERE  M.SODTYPE=51 AND M.COMPANY=1 AND M.CODE=:kod_an
      ) sub
WHERE rn IN (2)
这存储在变量
price2

我正在做一些编程(这是vbscript):


仅使用SQL如何实现这一点?

试试这样的方法。没有在缺少样本数据的情况下测试它,但是想法是首先在CTE中获得两行(rn=1和rn=2)。然后使用
case
语句查找
abs
值,并为
rn=
返回
0
PRICE

另外,我假设您的其余查询是正确的

;with t as (
SELECT 
      SUB.PRICE
FROM (
        SELECT 
               ML.PRICE
              , rn = row_number() over (PARTITION BY M.CODE ORDER BY FINDOC DESC)
        FROM  MTRLINES ML
              INNER JOIN MTRL M
                    ON M.MTRL = ML.MTRL  AND FINDOC IN (SELECT FINDOC FROM FINDOC WHERE SOSOURCE=1251 AND FPRMS IN (1,2)) 
              WHERE  M.SODTYPE=51 AND M.COMPANY=1 AND M.CODE=:kod_an
      ) sub
WHERE rn IN (1,2)
)
select case 
            when abs(sum(case when rn=1 
                            then price 
                            else (price * -1 ) 
                        end)
                    )
                    > 0.02  
        then (select price1 from t where rn=1) 
        else 0 end
         as result
from t
;

试试这样的。没有在缺少样本数据的情况下测试它,但是想法是首先在CTE中获得两行(rn=1和rn=2)。然后使用
case
语句查找
abs
值,并为
rn=
返回
0
PRICE

另外,我假设您的其余查询是正确的

;with t as (
SELECT 
      SUB.PRICE
FROM (
        SELECT 
               ML.PRICE
              , rn = row_number() over (PARTITION BY M.CODE ORDER BY FINDOC DESC)
        FROM  MTRLINES ML
              INNER JOIN MTRL M
                    ON M.MTRL = ML.MTRL  AND FINDOC IN (SELECT FINDOC FROM FINDOC WHERE SOSOURCE=1251 AND FPRMS IN (1,2)) 
              WHERE  M.SODTYPE=51 AND M.COMPANY=1 AND M.CODE=:kod_an
      ) sub
WHERE rn IN (1,2)
)
select case 
            when abs(sum(case when rn=1 
                            then price 
                            else (price * -1 ) 
                        end)
                    )
                    > 0.02  
        then (select price1 from t where rn=1) 
        else 0 end
         as result
from t
;
我可以建议:

with prices as (
      select code,
             max(case when seqnum = 1 then price end) as price_last,  
             max(case when seqnum = 2 then price end) as price_second,
             count(*) as num_prices 
      from (select ml.price, m.code,
                   row_number() over (partition by M.CODE order by FINDOC desc) as seqnum
            from MTRLINES ML inner join
                 MTRL M
                 ON M.MTRL = ML.MTRL and
                    FINDOC in (select FINDOC from FINDOC where SOSOURCE = 1251 and FPRMS in (1, 2)
                              ) 
            where M.SODTYPE = 51 and M.COMPANY = 1 and
                  M.CODE = :kod_an
           ) m
      where seqnum in (1, 2)
      group by code
     )
select (case when num_prices = 1 then price_last
             when abs(price_last - price_second) > 0.02 then price_last
             else 0
        end)
from prices;
请注意,您的代码一次只执行一个代码。您可以删除
M.code=:kod\u an
并在多个代码上运行代码。

我建议:

with prices as (
      select code,
             max(case when seqnum = 1 then price end) as price_last,  
             max(case when seqnum = 2 then price end) as price_second,
             count(*) as num_prices 
      from (select ml.price, m.code,
                   row_number() over (partition by M.CODE order by FINDOC desc) as seqnum
            from MTRLINES ML inner join
                 MTRL M
                 ON M.MTRL = ML.MTRL and
                    FINDOC in (select FINDOC from FINDOC where SOSOURCE = 1251 and FPRMS in (1, 2)
                              ) 
            where M.SODTYPE = 51 and M.COMPANY = 1 and
                  M.CODE = :kod_an
           ) m
      where seqnum in (1, 2)
      group by code
     )
select (case when num_prices = 1 then price_last
             when abs(price_last - price_second) > 0.02 then price_last
             else 0
        end)
from prices;

请注意,您的代码一次只执行一个代码。您可以删除
M.code=:kod_an
并在多个代码上运行代码。

Hi,它表示无效列名
rn
Hi,它表示无效列名
rn
很好!只需用
-
更正
,谢谢!当mtrlines表有一行时,例如,一个价格返回0。它应该返回Price1。请调查一下。当有两行或更多行时,它会工作。。@F.Mysir。有一种方法计算价格,并在逻辑中明确包含价格。那么我们如何添加if语句,使if mtrlines有一行返回价格1呢?在vbscript中,若第二个查询中并没有第二行,则返回0。所以我对Price1-Price2进行了分解,例如3.45-0>0.02,这是真的,输出为3.45。通过这个查询,我得到了0,在这种情况下,mtrlines有一行,这很好!只需用
-
更正
,谢谢!当mtrlines表有一行时,例如,一个价格返回0。它应该返回Price1。请调查一下。当有两行或更多行时,它会工作。。@F.Mysir。有一种方法计算价格,并在逻辑中明确包含价格。那么我们如何添加if语句,使if mtrlines有一行返回价格1呢?在vbscript中,若第二个查询中并没有第二行,则返回0。所以我对Price1-Price2进行了分解,例如3.45-0>0.02,这是真的,输出为3.45。通过这个查询,如果mtrlines有一行,我得到0