【问题标题】:Iterating through table to use as parameters in function to create large new table遍历表以用作函数中的参数以创建大型新表
【发布时间】:2013-07-01 10:56:57
【问题描述】:

我一直在研究这个,但还没有找到可用的答案。我是 SQL Server 的中度黑客,并且在函数和存储过程中使用参数方面取得了一些成功,但这是我似乎无法理解的组合。

为了清楚起见,我总结了以下场景: 我的公司以笔记本电脑、台式机和配件的形式销售电脑。我有一个 tbl_Computers,我在其中维护 Computer_Type、Model_Num 和 Mix_Percent,如下所示:

Desktop  ABC  .75  
Desktop  XYZ  .25  
Laptop   DEF  .60  
Laptop   MNO  .40

我们还有一个按月预测的表格,我在其中维护 Computer_Type、Jul_Num、Aug_Num 和 Sep_Num,如下所示:

Desktop  100  200  150  
Laptop   300  400  700

我创建了一个用于规划物料清单的功能,该功能将查找过去十二个月内针对给定型号销售的所有组件和配件。它的工作原理如下:
P_BOM ("ABC") 将生成一个包含两列的表:Component 和 Comp_Percent

CPU        1  (This means we sell 1 CPU with every desktop)  
Hard Drive 2  (We sell 2 with every desktop)  
Printer    .8 (80% of the time we sell a printer)

我希望我的存储过程做的是提供一个看起来像这样的单个组合表,其中包含以下标题 Component、Jul_Num、Aug_Num 和 Sep_Num:

CPU         400  600  850  
Hard Drive  500  800  1000

我通过对以下逻辑求和得到 CPU 编号:
桌面的 Jul_Num x ABC 的 Mix_Percentage x ABC 的 CPU Comp_Percent
桌面的 Jul_Num x XYZ 的 Mix_Percentage x XYZ 的 CPU Comp_Percent
笔记本电脑的 Jul_Num x ABC 的 Mix_Percentage x ABC 的 CPU Comp_Percent
笔记本电脑的 Jul_Num x XYZ 的 Mix_Percentage x XYZ 的 CPU Comp_Percent
400 = (100 x .75 x 1) + (100 x .25 x 1) + (300 x .6 x 1) + (300 x .4 x 1)

有什么想法吗?

谢谢,

编辑:

感谢建议,这不必是一个迭代问题,而是一个基于表格的解决方案。

我创建了第一个表给我:

ABC CPU          3  3   1
ABC Hard Drive   6  3   2
DEF CPU          2  2   1
DEF Hard Drive   2  2   1
MNO CPU          1  1   1
MNO Hard Drive   1  1   1
XYZ CPU          1  1   1
XYZ Hard Drive   2  1   2

这是 SQL:

SELECT        All_Components.Model_Num, All_Components.Part_Num, SUM(All_Components.Qty) AS Total, TTO.Target_Total, SUM(All_Components.Qty) 
                     / TTO.Target_Total AS Comp_Percent
FROM            (SELECT        Test_tbl_Computers.Model_Num, Test_tbl_Orders_2.Order_Num, Test_tbl_Orders_2.Part_Num, Test_tbl_Orders_2.Qty
                      FROM            Test_tbl_Orders AS Test_tbl_Orders_2 CROSS JOIN
                                                Test_tbl_Computers) AS All_Components INNER JOIN
                         (SELECT        Test_tbl_Orders.Part_Num, SUM(Test_tbl_Orders.Qty) AS Target_Total
                           FROM            Test_tbl_Orders INNER JOIN
                                                     Test_tbl_Computers AS Test_tbl_Computers_1 ON Test_tbl_Orders.Part_Num = Test_tbl_Computers_1.Model_Num
                           GROUP BY Test_tbl_Orders.Part_Num) AS TTO ON All_Components.Model_Num = TTO.Part_Num
WHERE        (All_Components.Order_Num IN
                         (SELECT        Order_Num
                           FROM            Test_tbl_Orders AS Test_tbl_Orders_1
                           WHERE        (Part_Num = All_Components.Model_Num))) AND (All_Components.Part_Num <> All_Components.Model_Num)

然后,为了防止它成为我无法驯服的 SQL 怪物,我创建了另一个函数来对预测和混合百分比进行内部连接,然后将所有按 Part_Num 分组的数字相加。

如果没有别的,我很高兴能写下我的问题以帮助我集中注意力。

【问题讨论】:

    标签: sql function stored-procedures iteration


    【解决方案1】:

    我不明白你为什么需要一个函数。您在此处说明的所有数据都可以存储在表中,然后通过简单的连接获取。 即使 BOM 是递归的,您也可以使用 CTE。

    如果您坚持使用该函数,您可以使用CROSS APPLY 对每一行调用该函数。


    到目前为止,我创建的唯一功能是创建一个 包含在同一销售额中销售的所有组件的两列表 订购为特定的桌面型号。你建议我发帖吗 该表的结果到另一个表并继续插入新的 函数的每个实例的行?

    我明白了,你不需要使用函数。 有很多不同的可能性,

    您可能非常接近它,正在将函数转换为 SP 并使用

    INSERT INTO [TableName]
    EXEC [SP_NAME]
    

    另一个将查询转换为累积子查询或 CTE(见下文) 和其他人一起加入。

    一般尽量避免每次都创建函数,因为它们会对数据库造成很大的破坏。

    BOM 不是递归的。我对CTE不熟悉。

    当您有许多串联的子查询时,公用表表达式 (CTE) 是很好的工具,一旦您习惯了它们,它们就会为复杂的查询带来很多清晰 (IMO)。 CTE 还为递归提供本机支持。 网上有很多文章可以指导你。只是谷歌 CTE 示例或 CTE 教程

    我没有使用 CROSS APPLY 的经验。

    交叉申请:来自页面http://technet.microsoft.com/en-us/library/ms175156(v=sql.105).aspx

    APPLY 运算符允许您为查询的外部表表达式返回的每一行调用表值函数。

    最后也是最重要的

    任何例子都将不胜感激

    如果你能给我你已经拥有的部分脚本,我会尝试将其转换为我打算指导你的查询。

    【讨论】:

    • 到目前为止,我创建的唯一功能是创建一个包含两列的表格,其中包含在与特定桌面型号相同的销售订单上销售的所有组件。您是否建议我将该表的结果发布到另一个表并继续为函数的每个实例插入新行? BOM 不是递归的。我对CTE不熟悉。我没有 CROSS APPLY 的经验。任何示例将不胜感激。
    • @user2547072,你问的问题太多了,只能发表评论,请参阅我的扩展编辑答案。
    • Luis,谢谢你指点我 CTE 的!!!每当我能找到它时,我都会欣赏更具可读性的代码。你改变了我的编程风格!
    • @user2547072 如果您将我的回复标记为已接受,我将不胜感激?我现在开始参加 Stackoverflow,我发现获得的积分对我的参与方式有影响
    【解决方案2】:

    “Computer_Type、Jul_Num、Aug_Num 和 Sep_Num”

    每月一列适用于报告或数据输入界面,但如果你真的以这种方式存储数据,你会让自己发疯。如果您有办法返回并将该表更改为“Computer_Type, Year, Month, Num”或“Computer_Type, Date, Num”,那么您应该首先这样做。

    【讨论】:

    • 感谢您的建议。但是,您将如何使用您的格式创建用于数据输入的 ASP.net GridView?我希望能够根据 Computer_Type、Jul_Num、Aug_Num 和 Sep_Num 约定显示和编辑“桌面”的单行中的所有数字。目前,我正在为每个明确标记为 Jul_Num 等的列添加一个新的 ItemTemplate。
    猜你喜欢
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 2018-04-12
    • 1970-01-01
    • 1970-01-01
    • 2021-03-31
    相关资源
    最近更新 更多