SQL Server:选择总和与值匹配的最新行

时间:2017-03-22 14:46:31

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

这是一张表......

ID    QTY    DATE    CURRENT_STOCK
----------------------------------
1     1      Jan     30
2     1      Feb     30
3     2      Mar     30
4     6      Apr     30
5     8      May     30
6     21     Jun     30

我需要返回总和数量等于或超过当前库存水平的最新行,一旦达到此总数,就不包括任何其他行,所以我希望只看到这些行......

ID    QTY    DATE    CURRENT_STOCK
----------------------------------
4     6      Apr     30
5     8      May     30
6     21     Jun     30

我假设我需要一个CTE(通用表格表达式),并查看了this question,但无法看到如何将其转换为我的要求。

帮助!?

4 个答案:

答案 0 :(得分:3)

Declare @YourTable table (ID int,QTY int,DATE varchar(25), CURRENT_STOCK int)
Insert Into @YourTable values
(1     ,1      ,'Jan'     ,30),
(2     ,1      ,'Feb'     ,30),
(3     ,2      ,'Mar'     ,30),
(4     ,6      ,'Apr'     ,30),
(5     ,8      ,'May'     ,30),
(6     ,21     ,'Jun'     ,30)


Select A.*
 From  @YourTable A
 Where ID>= (
                Select LastID=max(ID)
                 From  @YourTable A
                 Cross Apply (Select RT = sum(Qty) from @YourTable where ID>=A.ID) B
                 Where B.RT>=CURRENT_STOCK
             )

<强>返回

ID  QTY DATE    CURRENT_STOCK
4   6   Apr     30
5   8   May     30
6   21  Jun     30

答案 1 :(得分:1)

使用提供的数据集执行此操作的一种方法

if object_id('tempdb..#Test') is not null drop table #Test
create table #Test (ID int, QTY int, Date_Month nvarchar(5), CURRENT_STOCK int)

insert into #Test (ID, QTY, Date_Month, CURRENT_STOCK)
values
(1, 1, 'Jan', 30),
(2, 1, 'Feb', 30),
(3, 2, 'Mar', 30),
(4, 6, 'Apr', 30),
(5, 8, 'May', 30),
(6, 21, 'Jun', 30)

if object_id('tempdb..#Finish') is not null drop table #Finish
create table #Finish (ID int, QTY int, Date_Month nvarchar(5), CURRENT_STOCK int)

declare @rows int = (select MAX(ID) from #Test)
declare @stock int = (select MAX(CURRENT_STOCK) from #Test)
declare @i int = 1
declare @Sum int = 0
while @rows > @i
BEGIN
    select @Sum = @Sum + QTY from #Test where ID = @rows 

    IF (@SUM >= @stock)
    BEGIN
        set @i = @rows + 1 -- to exit loop
    END

    insert into #Finish (ID, QTY, Date_Month, CURRENT_STOCK)
    select ID, QTY, Date_Month, CURRENT_STOCK from #Test where ID = @rows 

    set @rows = @rows - 1
END

select * from #Finish

答案 2 :(得分:0)

设置测试数据

-- Setup test data
CREATE TABLE #Stock
    ([ID] int, [QTY] int, [DATE] varchar(3), [CURRENT_STOCK] int)
;

INSERT INTO #Stock
    ([ID], [QTY], [DATE], [CURRENT_STOCK])
VALUES
    (1, 1, 'Jan', 30),
    (2, 1, 'Feb', 30),
    (3, 2, 'Mar', 30),
    (4, 6, 'Apr', 30),
    (5, 8, 'May', 30),
    (6, 21, 'Jun', 30)
;

SQL Server 2012 +

的解决方案

如果你有一个支持全窗口函数语法的更新版本的SQL服务器,你可以这样做:

-- Calculate a running total of qty by Id descending
;WITH stock AS (
    SELECT *
          -- This calculates the SUM over a 'window' of rows based on the first
          -- row in the result set through the current row, as specified by the
          -- ORDER BY clause
          ,SUM(qty) OVER(ORDER BY Id DESC 
                         ROWS BETWEEN UNBOUNDED PRECEDING 
                            AND CURRENT ROW) AS TotalQty
    FROM #Stock
),
-- Identify first row in mininum set that matches or exceeds CURRENT_STOCK
first_in_set AS (
    SELECT TOP 1 *    
    FROM stock
    WHERE TotalQty >= CURRENT_STOCK
)
-- Fetch matching set
SELECT *
FROM #stock
WHERE Id >= (SELECT Id FROM first_in_set)

SQL Server 2008的解决方案

对于只对窗口函数有基本支持的SQL Server 2008,您可以使用CROSS APPLY计算运行总计:

-- Calculate a running total of qty by Id descending
;WITH stock AS (
    SELECT *
          -- This window function causes the results of this query
          -- to be sorted in descending order by Id
          ,ROW_NUMBER() OVER(ORDER BY Id DESC) AS sort_order   
    FROM #Stock s1
    -- CROSS APPLY 'applies' the query (or UDF) to every row in a result set
    -- This CROSS APPLY query produces a 'running total'
    CROSS APPLY (
        SELECT SUM(Qty) AS TotalQty
        FROM #Stock s2
        WHERE s2.Id >= s1.id
    ) total_calc
    WHERE TotalQty >= s1.CURRENT_STOCK
),
-- Identify first row in mininum set that matches or exceeds CURRENT_STOCK
first_in_set AS (
    SELECT TOP 1 Id
    FROM stock
    WHERE sort_order = 1
)
-- Fetch matching set
SELECT *
FROM #stock
WHERE Id >= (SELECT Id 
             FROM first_in_set)

答案 3 :(得分:-1)

你必须解释更多你想做什么。

也许这可以帮到你

从示例中选择*,其中qty&gt; curr_stock order by id desc limit 3;

///////////////抱歉开头不明白

这是你想要做的也跑进sql server。 http://img.fenixzone.net/i/sOwA13L.png

设置@t:= 0; 选择 id,qty,date_,curr_stock 来自id的示例组具有curr_stock&gt; =(@t:=(@t + qty))id by id desc;

如果您愿意,可以使用存储的程序