我是否可以仅使用SQL查询执行此操作,还是需要存储过程?

时间:2009-11-17 16:18:01

标签: sql-server stored-procedures

我遇到了一个需要一些建议/帮助的问题。

背景 我在会计软件中编写一张地图,需要特殊的格式和帐户代码之间的树状层次结构,即:

  • 帐户1是帐户11,12和13的父亲;
  • 另一方面,帐户11是帐户111,112和113的父亲;
  • 也可能存在类似这样的帐户关系:帐户12是帐户12111的父亲,因为没有121或1211,这意味着如果我自己创建,则层次结构不是“一位数加层次”明确;
  • 这种逻辑一直持续到地图结束。

数据库表格背景 所有过程都涉及3个表。

  1. 总分类帐表(名为ContasPoc ),我可以通过每个帐号代码与表号2(总帐分录帐户)相关联,换句话说,表1中的帐户代码等于表2中的帐户代码(此字段在两个表中都命名为CodigoConta )。
  2. 总分类帐分录帐户(名为LancamentosContas ),我可以与表号1(总分类帐)相关,正如我所说。此表还与ID表3(总帐分录)相关。
  3. 表3是我所说的总帐分录(名为Lancamentos ),与此表相关的字段名称是IdLancamento 。我需要此表进行过滤。
  4. 一个真实的例子: 我希望24到26岁的所有账户都有价值/动作,但我也想要他们的父母。此外,他们的父母将必须包含他们的子帐户的总和,就像下面的示例输出:

    Account Code | Debit Sum | Credit Sum | Balance  /*Balance = Debit Sum - Credit Sum*/
    24           | 12,000    | 184,000    | -172,000 /*Sum of all children (242+243)   */
    242          | 12,000    | 48,000     | -36,000  /*Sum of all children (2423+2424) */
    2423         | 12,000    | 0,000      |  12,000  /*Sum of all children (24231)     */
    24231        | 0,000     | 0,000      |  12,000  /*Account with values/movements   */
    2424         | 0,000     | 48,000     | -48,000  /*Sum of all children (24241)     */
    24241        | 0,000     | 48,000     | -48,000  /*Account with values/movements   */
    243          | 0,000     | 136,000    | -136,000 /*Sum of all children (2433)      */
    2433         | 0,000     | 136,000    | -136,000 /*Sum of all children (24331)     */
    24331        | 0,000     | 136,000    | -136,000 /*Sum of all children (243313)    */
    243313       | 0,000     | 136,000    | -136,000 /*Account with values/movements   */
    

    正如您所看到的,有很多帐户,但只有具有以下评论的帐户/*Account with values/movements*/有值,其他帐户由我计算,这让我想到了真正的问题:

    我可以这样做吗?当然,但目前我正在使用递归方法和几个查询来执行此操作,这种方法花费了大量时间,所以我肯定需要一个新的,因为大多数客户都使用旧计算机。

    我试图使用INNER JOINS的查询来获取这种结构/数据。没有用,因为我没有得到我需要的所有数据,只有带动作的线条。

    我也尝试过LEFT JOINS。工作得不好,因为我得到了我需要的所有数据以及我不需要的很多数据。但是使用LEFT JOIN还有一个问题,如果我不在WHERE子句中包含表3中的任何字段,我只能得到这些额外数据(也是我需要的数据)。这显然有一个答案,但因为我不是SQL Server的专家,我不知道是什么原因。

    以下是我构建的查询(另一个只有1个差异,LEFT JOIN而不是第一个INNER JOIN):

    SELECT IdConta, Min(IdContaPai) AS IdContaPai, Min(ContasPoc.CodigoConta) AS CodigoConta
    FROM ContasPoc INNER JOIN (LancamentosContas INNER JOIN Lancamentos ON 
    Lancamentos.IdLancamento = LancamentosContas.IdLancamento) ON ContasPoc.CodigoConta = 
    LancamentosContas.CodigoConta
    WHERE Lancamentos.IdEmpresa=17 AND ContasPoc.IdEmpresa=17 AND Lancamentos.IdLancamento = 
    LancamentosContas.IdLancamento AND ContasPoc.CodigoConta>='24' AND ContasPoc.CodigoConta<='26'
    GROUP BY IdConta 
    ORDER BY Min(ContasPoc.CodigoConta)
    

    经过长时间的解释(对不起),我的3个问题是:

    1. 是否可以仅使用数据库查询获得此类结果(如上所述),换句话说,不使用递归方法?
    2. 如果不是(最有可能)存储过程的方法,如果是这样,我该怎么做(以前从未使用过它们)?
    3. 我还没有看到另一种方法吗?
    4. 有人可以帮我这个吗?

      我希望我收到所有相关数据,但如果不是,请告诉我忘了什么,我很乐意回答。提前致谢! 米格尔

4 个答案:

答案 0 :(得分:2)

WITH    q (AccountCode, Balance) AS (
        SELECT  24231, 12000
        UNION ALL
        SELECT  243313, -136000
        UNION ALL
        SELECT  24241, -48000
        UNION ALL
        SELECT  24, NULL
        UNION ALL
        SELECT  242, NULL
        UNION ALL
        SELECT  2423, NULL
        )
SELECT  qp.AccountCode, SUM(qc.Balance)
FROM    q qp
JOIN    q qc
ON      SUBSTRING(CAST(qc.AccountCode AS VARCHAR), 1, LEN(qp.AccountCode)) = qp.AccountCode
GROUP BY
        qp.AccountCode
ORDER BY
        AccountCode

答案 1 :(得分:1)

除非我弄错了,否则如果您将帐户代码视为字符串,这就变得容易了。您可以查询:

select *,
    (select sum(vw2.DebitSum)
     from SomeView vw2
     where vw.code < vw2.code and 
           vw2.code < cast(cast(vw.code as int) + 1 as varchar)
    ) as DebitSum
from SomeView vw
where '24' <= vw.code and vw.code < '27'

子查询总结了所有孩子的借方。

答案 2 :(得分:0)

您永远不需要“存储过程”。可以这样想,存储过程只是在其中包含DB查询的代码,它完全在服务器上运行。您始终可以使用客户端语言执行该代码,并让数据库查询返回您在客户端操作的结果集。

答案 3 :(得分:0)

我不明白为什么你不只是拥有一个主键ID的帐户表,并且每个子帐户都有一个父帐户字段。然后,您只需引用帐户表并在循环cte中获取层次结构。