Sql 查询以查找行中的特定总和
Posted
技术标签:
【中文标题】Sql 查询以查找行中的特定总和【英文标题】:Sql Query to find specific sum in rows 【发布时间】:2021-12-31 06:39:58 【问题描述】:这是由该查询生成的调色板列表:
select STO_COD_ART PRODUCT_NAME,STO_NUMPAL PALETTE_NUMBER,STO_PNET NET_WEIGHT
from GCSTOCK
where STO_COD_ART = '739155VPFK500'
and STO_OUTDATE is null;
PRODUCT_NAME | PALETTE_NUMBER | NET_WEIGHT |
---|---|---|
739155VPFK500 | 227881 | 770 |
739155VPFK500 | 241691 | 894 |
739155VPFK500 | 246221 | 975 |
739155VPFK500 | 246471 | 861 |
739155VPFK500 | 246531 | 882 |
(derived from this image)
我正在尝试选择总和 sum(NET_WEIGHT)
在 1600 和 1700 之间的最小行数。
我已尝试使用以下查询,但未返回预期结果:
select STO_COD_ART PRODUCT_NAME,STO_NUMPAL PALETTE_NUMBER,STO_PNET NET_WEIGHT
from GCSTOCK
where STO_COD_ART = '739155VPFK500'
and STO_OUTDATE is null
group by STO_COD_ART, STO_NUMPAL, STO_PNET
having (SUM(STO_PNET) >= 1600 and SUM(STO_PNET) <= 1700);
我相信尝试将
GROUP BY
与HAVING CLAUSE
一起使用是行不通的,因为我需要原始形式的结果,而不是分组结果的 1 条记录,我需要某种方法来验证最少的数字可能的记录用于创建组。
The expected result would be:
PRODUCT_NAME | PALETTE_NUMBER | NET_WEIGHT |
---|---|---|
739155VPFK500 | 227881 | 770 |
739155VPFK500 | 241691 | 894 |
感谢您的帮助
【问题讨论】:
你能澄清一下“在这个列表中搜索一个 这不起作用,因为您在 group by 子句中添加了自动增量字段 你的意思是,如果托盘 STO_PNET 为 n,则找到另一个 STO_PNET 在列表中,查询将选择一个二或三个...(我们不知道)STO_ID 和 sum(STO_PNET) 尽可能与 1500 最接近。 请根据您提供的源数据使用您期望的结果更新问题 【参考方案1】:拣选最少数量的托盘以满足数量的概念是基于这样一种理念,即抓取和移动托盘是劳动/时间密集型的,应尽量减少以实现最佳的整个过程。
如果这是一个测试问题那么很好,这个答案会起作用,但这个概念在现实中是有缺陷的,因为理论上它需要在仓库的整个生命周期内无限量的存储,如果它也将接收库存。实际上,我们要么先选择整个托盘(如果不需要重新包装),要么先从数量最少的托盘中挑选,以最大限度地利用存储空间并为新到货的仓库腾出空间。如果需要尽量减少货物的变质或老化,那么您将首先从最旧的托盘中挑选。
要获得最少的托盘数量,我们确实需要评估所有或至少许多托盘组合,然后选择具有最少托盘的组合。在 SQL 中,我们可以使用递归 CTE 来构建我们想要考虑的所有可能组合的矩阵,然后我们可以根据您的业务逻辑对这些结果进行排序,并将该列表中的第一个结果作为 最佳 组合。
然后,您将采用 最佳 组合并从原始来源重新查询以产生您的应用程序所期望的结果。
在可以用 C#、Python、javascript 甚至在存储过程中执行的程序代码过程中,我们通常会使用一种算法,首先选择最大的托盘,然后遍历剩余的托盘并选择下一个最大的托盘仍然满足标准的托盘。递归 CTE 可以产生相同的结果,但它以不同的方式表示。
MS Sql Server version of a Recursive CTE for this can be viewed here,在该示例中,我添加了一些额外的托盘定义,并允许最多 4 个托盘组合。您可以根据需要选择允许更多或更少的组合。
假设最佳标准是由托盘形成的矩阵是具有最大组合重量的组合,如下表所示:
PIndex | Pallet_1 | Pallet_2 | Pallet_3 | Pallet_4 | NET_WEIGHT |
---|---|---|---|---|---|
2 | 241691 | 227881 | (null) | (null) | 1664 |
2 | 246531 | 227881 | (null) | (null) | 1652 |
2 | 246471 | 227881 | (null) | (null) | 1631 |
但如果最佳标准是首先挑选最旧的托盘(托盘编号越低表示旧托盘),则矩阵中的项目顺序不同:http://sqlfiddle.com/#!18/201c3/6
PIndex | Pallet_1 | Pallet_2 | Pallet_3 | Pallet_4 | NET_WEIGHT |
---|---|---|---|---|---|
2 | 241691 | 227881 | (null) | (null) | 1664 |
2 | 246471 | 227881 | (null) | (null) | 1631 |
2 | 246531 | 227881 | (null) | (null) | 1652 |
微妙,并且不会改变此特定数据集中的结果,而是更改具有不同托盘和数量的数据集,或者实际上如果您在移除之前的托盘后再次运行此程序,那么排序对您来说可能很重要。
您可能可以使用第一条记录,因此在您的应用程序中从该集合中选择TOP 1
,但如果从原始数据集中选择其他属性很重要,我们可以简单地使用此输出来过滤(或连接)源数据:
查看完整的小提琴:http://sqlfiddle.com/#!18/201c3/7
WITH FilteredPallets as (
SELECT STO_COD_ART,STO_NUMPAL,STO_PNET
FROM GCSTOCK
WHERE STO_COD_ART = '739155VPFK500'
AND STO_OUTDATE is null
AND STO_PNET <= 1700
), PalletHierarchy as (
SELECT 1 as PIndex
, STO_NUMPAL as Pallet_1, CAST(null as int) as Pallet_2, CAST(null as int) as Pallet_3, CAST(null as int) as Pallet_4
, STO_PNET as NET_WEIGHT, STO_PNET as Last_Weight
FROM FilteredPallets
UNION ALL
SELECT 2
, P1.Pallet_1, P2.STO_NUMPAL as Pallet_2, null, null
, P2.STO_PNET + P1.NET_WEIGHT as NET_WEIGHT, P2.STO_PNET as Last_Weight
FROM PalletHierarchy P1, FilteredPallets P2
WHERE P1.PIndex = 1
AND P2.STO_NUMPAL <> P1.Pallet_1
AND P2.STO_PNET <= P1.Last_Weight
AND (P2.STO_PNET + P1.NET_WEIGHT) <= 1700
UNION ALL
SELECT 3
, P1.Pallet_1, P1.Pallet_2, P2.STO_NUMPAL as Pallet_3, null
, P2.STO_PNET + P1.NET_WEIGHT as NET_WEIGHT, P2.STO_PNET as Last_Weight
FROM PalletHierarchy P1, FilteredPallets P2
WHERE P1.PIndex = 2
AND P2.STO_NUMPAL <> P1.Pallet_1 AND P2.STO_NUMPAL <> P1.Pallet_2
AND P2.STO_PNET <= P1.Last_Weight
AND (P2.STO_PNET + P1.NET_WEIGHT) <= 1700
UNION ALL
SELECT 4
, P1.Pallet_1, P1.Pallet_2, P1.Pallet_3, P2.STO_NUMPAL as Pallet_4
, P2.STO_PNET + P1.NET_WEIGHT as NET_WEIGHT, P2.STO_PNET as Last_Weight
FROM PalletHierarchy P1, FilteredPallets P2
WHERE P1.PIndex = 3
AND P2.STO_NUMPAL <> P1.Pallet_1 AND P2.STO_NUMPAL <> P1.Pallet_2 AND P2.STO_NUMPAL <> P1.Pallet_3
AND P2.STO_PNET <= P1.Last_Weight
AND (P2.STO_PNET + P1.NET_WEIGHT) <= 1700
), Optimal as (
SELECT TOP 1 * FROM PalletHierarchy
WHERE NET_WEIGHT >= 1600
--ORDER BY PIndex ASC, NET_WEIGHT DESC
-- sort by age
ORDER BY PIndex ASC, Pallet_1, Pallet_2, Pallet_3, Pallet_4
)
SELECT STO_COD_ART as PRODUCT_NAME,STO_NUMPAL as PALETTE_NUMBER,STO_PNET as NET_WEIGHT
FROM GCSTOCK
INNER JOIN Optimal P1 ON P1.Pallet_1 = GCSTOCK.STO_NUMPAL
OR P1.Pallet_2 = GCSTOCK.STO_NUMPAL
OR P1.Pallet_3 = GCSTOCK.STO_NUMPAL
OR P1.Pallet_4 = GCSTOCK.STO_NUMPAL
结果:
PRODUCT_NAME | PALETTE_NUMBER | NET_WEIGHT |
---|---|---|
739155VPFK500 | 227881 | 770 |
739155VPFK500 | 241691 | 894 |
【讨论】:
以上是关于Sql 查询以查找行中的特定总和的主要内容,如果未能解决你的问题,请参考以下文章
如何查询我的所有视图设计以查找 SQL Server 中的特定字符串?