Могу ли я сделать это только с помощью SQL-запросов или мне нужна хранимая процедура? - PullRequest
2 голосов
/ 17 ноября 2009

Я столкнулся с проблемой, в которой мне нужен совет / помощь.

Справочная информация: Я программирую карту в бухгалтерском программном обеспечении, которое требует специального форматирования и древовидной иерархии между кодами счетов, т. Е.

  • Счет 1 является отцом счетов 11, 12 и 13;
  • С другой стороны, счет 11 является отцом счетов 111, 112 и 113;
  • Могут также существовать отношения с учетной записью, подобные этой: учетная запись 12 является отцом учетной записи 12111, потому что нет 121 или 1211, что означает, что иерархия не является «одной цифрой плюс иерархия», если я сам Чисто;
  • И эта логика продолжается до конца карты.

Фон таблицы базы данных: Во всем процессе задействованы 3 таблицы.

  1. Таблица главной книги ( с именем ContasPoc ), которую я могу связать с таблицей № 2 (учетные записи записей главной книги) по каждому коду счета, другими словами, код счета в таблице 1 равен код счета в таблице 2 ( это поле называется CodigoConta в обеих таблицах ).
  2. Счета записей главной книги ( с именем LancamentosContas ), которые я могу связать с таблицей № 1 (главная книга), как я уже сказал. Эта таблица также связана с таблицей № 3 (записи главной книги) с помощью идентификатора.
  3. Таблица № 3 - это, как я уже сказал, записи в Главной книге ( с именем Lancamentos ), а имя поля , связывающее эту таблицу с номером 2, - IdLancamento . Мне нужна эта таблица для целей фильтрации.

Реальный пример: Я хочу, чтобы все учетные записи с 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 JOIN имеет еще одну проблему, я получаю эти дополнительные данные (также те, которые мне нужны) только в том случае, если я не включаю поля из таблицы № 3 в предложение WHERE. На это, очевидно, есть ответ, но поскольку я не такой специалист в SQL Server, я не понимаю, в чем причина.

Вот запрос, который я построил (другой имеет только 1 различие, левое соединение вместо первого 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. Есть ли другой метод, которого я не вижу?

Может ли кто-нибудь помочь мне в этом?

Я надеюсь, что я получил все соответствующие данные, но если нет, пожалуйста, скажите мне, что я забыл, и я с удовольствием отвечу. Заранее спасибо! Miguel

Ответы [ 4 ]

2 голосов
/ 17 ноября 2009
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 голос
/ 17 ноября 2009

Если я не ошибаюсь, это становится легко, если вы считаете код учетной записи строкой. Вы можете запросить как:

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'

Подзапрос суммирует дебеты для всех детей.

0 голосов
/ 17 ноября 2009

Я не понимаю, почему у вас не просто таблица учетных записей с идентификатором для первичного ключа, а для каждой дочерней учетной записи есть поле родительской учетной записи. затем вы просто возвращаетесь к таблице счетов и получаете свою иерархию в циклическом цикле.

0 голосов
/ 17 ноября 2009

Вам никогда не «нужны» хранимые процедуры. Подумайте об этом так: хранимая процедура - это просто код с запросами БД внутри, который полностью выполняется на сервере. Вы всегда можете сделать этот код на своем клиентском языке, и запросы БД будут возвращать наборы результатов, с которыми вы работаете на стороне клиента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...