生成具有两个值之间的SUM的所有行组

时间:2012-09-12 06:18:18

标签: sql sql-server

我有如下表(产品)

id  name      quality  weight
1   Demir-1   ST-1     10
2   Demir-2   ST-2      7
3   Demir-3   ST-1     20
4   Demir-2   ST-3      8
5   Demir-1   ST-3      6
6   Demir-4   ST-2     10
7   Demir-2   ST-2     12
8   Demir-1   ST-1     15
9   Demir-1   ST-3     10
10  Demir-3   ST-3      5
11  Demir-2   ST-2      5

现在,如果用户想要获得权重总和在20到25之间且name ='Result-2'的产品列表,那么结果应如下所示。所有组合必须显示在20到25之间的重量之和。

 id name      quality  weight    
  4 Demir-2   ST-3      8   
  7 Demir-2   ST-2     12   
 11 Demir-2  ST-2       5
------------------------------
  2 Demir-2   ST-2      7
  4 Demir-2   ST-3      8
 11 Demir-2   ST-2      5
------------------------------ 
------------------------------ 
  1 Demir-1   ST-1     10
  8 Demir-1   ST-1     15

你可以看到总和(重量)是25。

5 个答案:

答案 0 :(得分:4)

DECLARE @tblProducts TABLE(Id INT IDENTITY, ProductName varchar(50),Quality varchar(50), ProductWeight int)
INSERT INTO @tblProducts SELECT 'Demir-1','ST-1',10
INSERT INTO @tblProducts SELECT 'Demir-2','ST-2',7
INSERT INTO @tblProducts SELECT 'Demir-3','ST-1',20
INSERT INTO @tblProducts SELECT 'Demir-2','ST-3',8
INSERT INTO @tblProducts SELECT  'Demir-1','ST-3',6
INSERT INTO @tblProducts SELECT  'Demir-4','ST-2',10
INSERT INTO @tblProducts SELECT 'Demir-2','ST-2' ,12
INSERT INTO @tblProducts SELECT  'Demir-1','ST-1',15
INSERT INTO @tblProducts SELECT  'Demir-1','ST-3',10
INSERT INTO @tblProducts SELECT 'Demir-3','ST-3' ,5
INSERT INTO @tblProducts SELECT 'Demir-2' ,'ST-2 ',5

 ;WITH Cte (Id,ProductQuality,ProductIds,ProductNames,ProductQualities,ProductTotalWeight,ProductWeights,ProductName1,ProductName2) AS
(
    SELECT  Id
            ,Quality            
            , ',' + CAST(Id AS VARCHAR(MAX))  
            ,',' + CAST(ProductName AS VARCHAR(MAX))
            ,',' + CAST(Quality AS VARCHAR(MAX)) 
            ,ProductWeight
            , ',' + CAST(ProductWeight AS VARCHAR(MAX)) 
            ,ProductName
            ,CAST(ProductName AS VARCHAR(MAX))
    FROM @tblProducts
    UNION ALL
    SELECT p.Id
            , p.Quality            
            ,c.ProductIds + ',' +  CAST(p.Id AS VARCHAR(MAX))
            ,c.ProductNames + ',' +  CAST(p.ProductName AS VARCHAR(MAX)) 
             ,c.ProductQualities + ',' + CAST(p.Quality AS VARCHAR(MAX)) 
             ,c.ProductTotalWeight + p.ProductWeight          
            ,c.ProductWeights + ',' + CAST(p.ProductWeight AS VARCHAR(MAX))
            ,p.ProductName
            ,c.ProductName2
    FROM @tblProducts AS p JOIN Cte c ON p.Id < c.Id
    WHERE  p.ProductName = c.ProductName2
    )
SELECT 
        ProductIds = STUFF(ProductIds,1,1,'')
        ,ProductNames = STUFF(ProductNames,1,1,'')
        ,ProductQualities = STUFF(ProductQualities,1,1,'')
        ,ProductTotalWeight
        ,ProductWeights = STUFF(ProductWeights,1,1,'')
FROM CTE 
WHERE ProductTotalWeight BETWEEN 20 AND 25

<强>结果

ProductIds  ProductNames             ProductQualities   ProductTotalWeight  ProductWeights
3           Demir-3                 ST-1                20                  20
11,7,2      Demir-2,Demir-2,Demir-2 ST-2 ,ST-2,ST-2     24                  5,12,7
11,7,4      Demir-2,Demir-2,Demir-2 ST-2 ,ST-2,ST-3     25                  5,12,8
11,4,2      Demir-2,Demir-2,Demir-2 ST-2 ,ST-3,ST-2     20                  5,8,7
10,3        Demir-3,Demir-3         ST-3,ST-1           25                  5,20
9,1         Demir-1,Demir-1         ST-3,ST-1           20                 10,10
9,8         Demir-1,Demir-1         ST-3,ST-1           25                 10,15
8,1         Demir-1,Demir-1         ST-1,ST-1           25                 15,10
8,5         Demir-1,Demir-1         ST-1,ST-3           21                  15,6
7,4         Demir-2,Demir-2         ST-2,ST-3           20                  12,8

答案 1 :(得分:2)

不幸的是,SQL不是正确的编码引擎,可以通过给定计算的表来提供所有组合,因为我一起黑客攻击的SQL代码显示。

通常我会建议这是用过程语言编写的,因为它的性质。 另请注意,此处的解决方案具有较大的输入数据集可能会快速耗尽SQL的递归限制。可能的产品数量也会增长到足够大的数量,而且运行速度非常慢。

drop table products
drop table #MinW
drop table #Products
go
create table products
(
id  int,
name  varchar(20),  
quality varchar(20),
[weight] int
) 
go
insert into products
select
1,   'Demir-1',   'ST-1',     10 
union
select 2,   'Demir-2',   'ST-2',      7 
union
select 3,   'Demir-3',   'ST-1',     20 
union
select 4,   'Demir-2',   'ST-3',      8 
union
select 5,   'Demir-1',   'ST-3',      6 
union
select 6,   'Demir-4',   'ST-2',     10 
union
select 7,   'Demir-2',   'ST-2',     12 
union
select 8,   'Demir-1',   'ST-1',     15 
union
select 9,   'Demir-1',   'ST-3',     10 
union
select 10,  'Demir-3',   'ST-3',      5 
union
select 11,  'Demir-2',   'ST-2',      5 
go
select 
p.id, p.name, p.quality, p.weight
into #MinW
from products p
inner join
(
select name,min(weight) as weight
from products group by name having min(weight) < 25
) as minW
on p.name = minW.name and p.weight = minW.weight

go
with weightProducts (id, name, [weight],history)
as
( 
select id, name,[weight],convert(varchar(1024),'"'+convert(varchar(10),id)+'",') from #minW
union all
select products.id, products.name,products.[weight] + weightProducts.[weight],convert(varchar(1024),weightProducts.history+'"'+convert(varchar(10),products.id)+'",') from products, weightProducts where products.name = weightproducts.name and  charindex('"'+convert(varchar(10),products.id)+'",',weightProducts.history)<=0 and (products.weight + weightProducts.weight) < 25
)
-- Statement using the CTE
select *
into #Products
from weightProducts
where weight between 20 and 25

go

select 
p1.history,
p2.id,
p2.quality,
p2.weight,
p1.weight as totalWeight
from #Products p1
inner join
products p2 on p1.name = p2.name and charindex('"'+convert(varchar(10),p2.id)+'",',p1.history)>0
order by 
p1.history,
p2.id 

答案 2 :(得分:0)

SELECT * FROM tablename
WHERE name IN (
 SELECT name FROM tablename 
 GROUP BY name
 HAVING SUM(weight) BETWEEN 20 AND 25)

答案 3 :(得分:0)

这个查询怎么样:

select id, name, quality, weight from PRODUCTS
group by id, name, quality, weight
having sum(weight) between 20 and 25

答案 4 :(得分:0)

试试这个:

SELECT * FROM products
WHERE name IN (
              SELECT name FROM products
              GROUP BY name
              HAVING SUM(weight) BETWEEN 20 AND 25)