【问题标题】:SQL Server-- join tables and SUM columns for each distinct rowSQL Server——为每个不同的行连接表和 SUM 列
【发布时间】:2011-01-13 18:23:37
【问题描述】:

有人可以仔细检查我的 SQL 语句是否正确操作和一般常识方法吗?

这是怎么回事:我有一个具有一对多关系的父表和子表,它们连接到一个名为 AccountNumberKey 的列上。子表中有数字列,我需要总结一下。

数据使得具有给定 AccountNumberKey 值的所有子记录在它们的两个数字列中始终具有相同的值。我想加入这些表格并为 每个 AccountNumberKey 将这两列的总和放入一个临时表中。我只需要对给定每个 AccountNumberKey 的单个子记录中的列求和。

下面的一些示例数据将(我希望)使这一点更清楚:

Parent Table Columns


ParentID    InstitutionID    AccountNumberKey  

1       LocalHost            1873283  
2       Acme Brokers         3627389    
3       Dewey, Cheatem       1392876
4       NCC1701              8837273
5       Peyton Place         9981273


Child Table Columns


ChildID     AccountNumberKey    Value1      Value2       ProposalNumber
1               1873283         1000        100         58
2               1873283         1000        100         59
3               1873283         1000        100         60
4               1873283         1000        100         61

这是我的 SQL 语句:

    SELECT   DISTINCT  Parent.InstitutionID, AccountNumberKey, SUM(Child.Value1 + Child.Value2) as total
        INTO   #TempTable
        FROM         Parent 
            INNER JOIN
              Child ON Parent.AccountNumberKey = Child.AccountNumberKey 

        GROUP BY Parent.InstitutionID, Parent.AccountNumberKey, Child.ProposalNumber

目标是链接表并将数据放入临时表中,如下所示:

TempTable columns


InstitutionID       AccountNumberKey        Total
LocalHost           1873283             1100

我的 SQL 查询是否合格?在分组方面,我不是天才,我想知道这是否 A) 正确和 B) 一个好的方法,或者是否有更好的加入尝试。

谢谢!

【问题讨论】:

    标签: sql-server join sum aggregate-functions


    【解决方案1】:

    首先,如果“具有给定 AccountNumberKey 值的子记录在它们的两个数字列中始终具有相同的值”是真的,那么您的表架构不是正确的第三范式(3NF)。应该有另一个表,每个 AccountNumberKey 有一行,AccountNumberKey 作为键,Value1Value2 作为数据字段,并且您的查询应该连接到该表(使用 AccountNumberKey),以检索Value1Value2

    其次,在这种情况下,您不应该在不是键的父表列上将子表连接到父表。这将导致笛卡尔积(其中输出将包括连接两侧的每一行的多行,实际上对这些记录进行双倍或三倍计数......)AccountNumberKey 是父表的键吗?

    如果不是,则父表中唯一应该用作子表中 FK 的列是键列 ParentID

    如果它(如果AccountNumberKey 在父表中是唯一的),那么 Value1 和 Value2 列应该在父表中,而不是在子表中.

    【讨论】:

    • Charles,无论关键状态如何,您都可以加入任何您想要的列。虽然也许你说这是不可取的?服务器允许你加入任何你喜欢的东西。
    • @Emtucifor,是的,你是对的,我会编辑以明确这一点.. 加入 PK 以外的结果会产生笛卡尔积......但有时(不是这里)这就是你想要的...... .
    • @Charles,你可以以任何你喜欢的方式将任何桌子加入任何桌子,通常我不会无缘无故地超过 2NF,这很少值得。
    • @Charles,加入 PK 以外的东西不会产生笛卡尔积。无论列是否为 PK,无条件连接都会产生笛卡尔积。
    • @Paul Creasey:你“很少”超过 2NF 意味着我希望我永远不会与你合作。
    【解决方案2】:

    您的联接不会产生这些结果,因为 AccountNumberKey 不是唯一的联接会产生

    LocalHost           1873283             1100
    

    4 次,每个子记录一个,聚合后将产生 4400 作为值。

    【讨论】:

    • 其实这不是真的,因为他是按 Child.ProposalNumber 分组的。但他不会为父表中的每一行获取一行。
    【解决方案3】:

    这个查询会给出你想要的结果:

    SELECT
       P.InstitutionID,
       P.AccountNumberKey,
       Total = C.Value1 + C.Value2
    FROM
       Parent P
       INNER JOIN (
          SELECT DISTINCT AccountNumberKey, Value1, Value2
          FROM Child
       ) C ON P.AccountNumberKey = C.AccountNumberKey
    

    但我想回应其他人所说的:如果你可以对设计做任何事情,你应该做,因为它没有被规范化。 Child 表中的 Value1 和 Value2 确实属于 Parent 表,因为它们是关于 Parent 的。如果 Child 表中的两行具有相同 AccountNumberKey 的不同值集怎么办?您的数据将全是错误的,谁知道可能对业务造成什么样的灾难性后果?在这种情况下,上面的 DISTINCT 将失败并为父行返回两行。

    更新:

    larryq 说:

    至于 value1 和 value2 可能需要属于父表,以后可能会因每个 ProposalNumber/AccountNumberKey 组合而有所不同。

    在这种情况下,我给你的查询会给出奇怪的结果。您将如何决定为 AccountNumber 使用哪一组值?你总是想要最新的 ProposalNumber 吗?您想为每组不同的 Value1 和 Value2 查看一行吗?是否要加入另一个表以查找要使用的当前 ProposalNumber?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多