Что является более эффективным способом T-SQL для запроса таблицы с иерархическим типом данных - PullRequest
0 голосов
/ 11 ноября 2018

У меня есть таблица с именем Budgetline. Отслеживает строки бюджета для проектов (Гранты).

Схема

BudgetId       int
Amount         decimal
LoginUser      varchar
InsertDate     datetime
GrantPhaseID   int
BudgetChartID  int
Rootdir        hierarchyid
OverHead       decimal

Столбец Amount - это бюджетная сумма для строки бюджета. Строка бюджета может иметь суббюджетную линию. У суббюджетной линии может быть другая суббюджетная линия. Иногда может быть до 5 уровней.

Есть еще одна таблица TransactionsDetail; он отслеживает бюджетные расходы

Схема

TransactionDetailID  int
TransactionID        int
Amount               numeric
ExRateAmount         numeric
TransactionDate      date
BudgetId             int
InsertDate           datetime
OverHead             decimal
Paid                 bit
PaidDate             datetime
LoginUser            varchar

Проекты (Гранты) имеют фазы. Есть еще одна таблица GrantPhase для отслеживания этого.

Есть еще одна таблица с именем BudgetChart. Он содержит список Budgetlines. Разные проекты (гранты) могут иметь одинаковые бюджетные линии.

Ниже приведена полная табличная функция для получения строк Sub бюджета (потомков) строки бюджета (Parent).

ALTER FUNCTION [dbo].[getSUBS]
    (@BudgetID INT
     --,@GrantPhaseID INT
    )
RETURNS @Mytable TABLE (CID INT,
                        [COUNT] INT,
                        DESCRIPTION VARCHAR(256),
                        AMOUNT NUMERIC(18,2),
                        SPENT NUMERIC(18,2),
                        BALANCE NUMERIC(18,2),
                        OVERHEAD NUMERIC(18,2)
                        --  BUDGETLIMIT numeric(18,2)
                       )
AS
BEGIN

-- get budgetline root level
declare @BudgetIDrootRevel int
SELECT @BudgetIDrootRevel = RootDir.GetLevel() FROM budgetlines WHERE budgetid = @BudgetID

-- GET GRANTPHASEID
DECLARE @GrantPhaseID int=(
select GrantPhaseID from BudgetLines where BudgetId=@BudgetID
)

DECLARE @RootDir HIERARCHYID
SELECT @RootDir = RootDir FROM budgetlines WHERE budgetid = @BudgetID
insert into @Mytable(
    CID 
,   [COUNT]
,   DESCRIPTION 
,   AMOUNT 
,   SPENT
,   BALANCE
,   OVERHEAD 
--, BUDGETLIMIT
)

SELECT
    BudgetId 
,   ROW_NUMBER() OVER (ORDER BY BudgetID DESC)
,   [Description]
,   dbo.[getBudgetAmount](BudgetLines.BudgetId)  AMOUNT --Sums all transactions made in the TransactionDetails table
,   [dbo].[getBudgetSpent](BudgetId) as SPENT
,   ISNULL((dbo.[getBudgetAmount](BudgetLines.BudgetId)-[dbo].[getBudgetSpent](BudgetId)),0) as BALANCE
,   BudgetLines.OVERHEAD
--, BUDGETLIMIT

FROM BudgetLines INNER JOIN BudgetChart 
ON BudgetChart.BudgetChartID = BudgetLines.BudgetChartID

WHERE RootDir.IsDescendantOf(@RootDir)=1
and GrantPhaseID = @GrantPhaseID
and Rootdir.GetLevel()=(@BudgetIDrootRevel+1)
--AND isBudgetline=1

return ;

end

Работает.

  • Таблица Budgetline имеет только 252 записи
  • В таблице TransactionDetails всего 172 записи

Мой вызов:

Требуется около 10 секунд, чтобы вернуть суббюджетные линии, если эта конкретная бюджетная линия имеет 3 или более подуровней (потомков).

Мой вопрос:

Есть ли лучший способ оптимизировать (переписать) эту функцию, чтобы она могла работать быстрее.

Ниже показано, как выглядит дизайн. Пользователь может просмотреть строки суббюджета, дважды щелкнув строку или нажав кнопку [Переместить вниз].

Как выглядит пользовательский интерфейс

Само собой разумеется: это мой первый пост о всемогущем стеке-потоке. Извините, если я нарушил какое-либо из правил сообщества. я еще учусь им.

1 Ответ

0 голосов
/ 11 ноября 2018

Вероятно, стоит указать, что вы запрашиваете / возможно, предполагаете, что "получить строки суббюджета" лучше всего сделать в базе данных, как только запрашивается строка основного бюджета

Учтите, что вы создаете пользовательский интерфейс, который понимает / отображает отношение мастер-детализация, и многое из этого можно сделать в пользовательском интерфейсе с большей эффективностью *, если подуровни не будут желательны все время. нет смысла преследовать и возвращать 5 уровней иерархических данных, если пользователь действительно хочет просматривать корневой уровень в пользовательском интерфейсе. Поэтому может быть лучше позволить пользовательскому интерфейсу управлять спросом на данные - просто возвращать соответствующие уровни, когда они запрашиваются пользователем

* эффективно с точки зрения: не тратить время БД на сбор ненужных данных / не передавать данные по сети, если они не будут использоваться

...