SQL Query根据聚合条件(列的总和)获取结果

时间:2011-12-29 10:38:48

标签: sql sql-server-2005 tsql

我有一张这样的表:

Product   sl_no Wt_Kg
Prod-001    1   3.000
Prod-002    2   4.000
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000
Prod-007    7   1.000
Prod-008    8   2.000
Prod-009    9   3.000
Prod-010    10  5.000
Prod-011    11  2.000
Prod-012    12  4.000

我需要此表中的所有记录从序列号开始,直到达到指定的重量总和(kgs)。
例如,如果我想从序列号(Sl_no)1获得权重小于或等于25千克的所有产品,我应该得到以下结果:

Product   sl_no Wt_Kg
Prod-001    1   3.000
Prod-002    2   4.000
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000

在下一个例子中,如果我希望所有产品都从序列号3开始,重量小于或等于30kgs,我应该得到以下结果:

Product   sl_no Wt_Kg
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000
Prod-007    7   1.000
Prod-008    8   2.000
Prod-009    9   3.000
Prod-010    10  5.000

请帮助我实现这一目标。提前谢谢......

4 个答案:

答案 0 :(得分:3)

这可能更有效率。我首先在我的数据库中创建一个名为_test的表,与您的描述相匹配。此解决方案利用了在UPDATE语句(http://haacked.com/archive/2004/02/28/sql-auto-increment.aspx)中递增值的功能。达到目标值后停止递增。如果您拥有数百万种产品,性能将成为一个问题,但您可以假设您将在一定数量的产品中达到目标重量(基于平均重量)并使用SET ROW_COUNT来限制最初的记录数量表变量。

DECLARE @Weight            REAL
DECLARE @SerialNumber      INT
DECLARE @MaxWeight         REAL

SET @Weight                = 0
SET @SerialNumber          = 3
SET @MaxWeight             = 30

DECLARE @Results TABLE
        (
        Product           CHAR(8),
        sl_no             INT,
        Wt_Kg             REAL,
        Total_Wt          REAL
        )

INSERT INTO
        @Results

(
        Product,
        sl_no,
        Wt_KG
)

SELECT
        Product,
        sl_no,
        Wt_KG

FROM
        _test

WHERE
        sl_no >= @SerialNumber  

ORDER BY
        sl_no


UPDATE
        @Results

SET 
        @Weight = Total_Wt = Wt_Kg + @Weight

WHERE 
        @Weight <= @MaxWeight


SELECT
        *

FROM 
        @Results

WHERE 
        Total_Wt <= @MaxWeight

结果是:

Product  sl_no       Wt_Kg         Total_Wt
-------- ----------- ------------- -------------
Prod-003 3           2             2
Prod-004 4           3             5
Prod-005 5           6             11
Prod-006 6           7             18
Prod-007 7           1             19
Prod-008 8           2             21
Prod-009 9           3             24
Prod-010 10          5             29

答案 1 :(得分:1)

declare @total decimal(9,3), @sl_no int
select @total = 25.000, @sl_no = 0 -- first case
--select @total = 30.000, @sl_no = 3 -- second case

;with tab (Product, sl_no, Wt_Kg) as (
    select 'Prod-001', 1, 3.000 union all
    select 'Prod-002', 2, 4.000 union all
    select 'Prod-003', 3, 2.000 union all
    select 'Prod-004', 4, 3.000 union all
    select 'Prod-005', 5, 6.000 union all
    select 'Prod-006', 6, 7.000 union all
    select 'Prod-007', 7, 1.000 union all
    select 'Prod-008', 8, 2.000 union all
    select 'Prod-009', 9, 3.000 union all
    select 'Prod-010', 10, 5.000 union all
    select 'Prod-011', 11, 2.000 union all
    select 'Prod-012', 12, 4.000
)
select t3.*
from tab t3
join (
    select t1.product, t1.sl_no, sum(t2.Wt_Kg) as total
    from tab t1
    join tab t2 on t1.sl_no >= t2.sl_no
    where t2.sl_no >= @sl_no
    group by t1.product, t1.sl_no
) t on t.product = t3.product and t.sl_no = t3.sl_no
where t.total <= @total

已添加:按sl_no分组和加入(仅在product不唯一的情况下)

结果是,第一种情况:

Product sl_no   Wt_Kg
Prod-001    1   3.000
Prod-002    2   4.000
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000

第二种情况:

Product sl_no   Wt_Kg
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000
Prod-007    7   1.000
Prod-008    8   2.000
Prod-009    9   3.000
Prod-010    10  5.000

答案 2 :(得分:1)

我的解决方案:

declare @total decimal(9,3), @sl_no int
select @total = 25.000, @sl_no = 1 -- first case


select * from Tab where sl_no<=
(
    select MAX(sl_no3) from (
        select t3.sl_no sl_no3, sum(t3.Wt_kg) Wt_kg3 from (
            select t1.sl_no sl_no, t2.Wt_Kg as Wt_kg from Tab t1, Tab t2 where t1.sl_no>=t2.sl_no and t2.sl_no >=@sl_no
        ) t3 group by t3.sl_no having SUM(t3.Wt_kg) <= @total
    ) t4
) and sl_no>=$sl_no

答案 3 :(得分:0)

如果序列号是唯一的:

第一个例子:

select *
from tableName
where sl_no >= 1
and Wt_Kg <= 25

第二个例子:

select *
from tableName
where sl_no >= 3
and Wt_Kg <= 30

如果序列号不唯一:

select Product, sl_no, Sum(Wt_Kg)
from tableName
where Wt_Kg <= 25
group by Product, sl_no

修改

如果您想按总和值过滤结果,可以试试这个:

select Product, sl_no, Sum(Wt_Kg)
from tableName
group by Product, sl_no
having (Sum(Wt_Kg) <= 25)

请记住,如果Product OR sl_no是唯一的而不是Sum()没有意义,那么聚合将用于共享特定值的记录。