【发布时间】:2021-01-01 22:40:27
【问题描述】:
我们有一个表 LedgerAccount,其父子关系类似于:
CREATE TABLE [dbo].[LedgerAccounts](
[ledger_key] [int] NOT NULL,
[Ledger] [nvarchar](12) NULL,
[LedgerLevel] [int] NULL,
[ParentAccount] [nvarchar](12) NULL,
[LedgerDescription] [nvarchar](30) NULL,
CONSTRAINT [PK_LedgerAccount] PRIMARY KEY CLUSTERED
(
[ledger_key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO [dbo].[LedgerAccounts]
VALUES (40, '020000', 0, '020999', 'Participation'),
(41, '020999', 20, '021000', 'Participation in Group'),
(42, '021000', 0, '021999', 'Loans to..'),
(43, '021999', 20, '022000', 'Loans to group company'),
(44, '022000', 0, '022999', 'Participation in'),
(45, '022999', 20, '029999', 'Other Participation'),
(46, '029999', 30, '059999', 'Financial Fixed Assets'),
(47, '059999', 50, 'TOT.BALANS', 'Fixed Assets'),
(48, 'TOT.BALANS', 90, 'TOT.GB', 'Total Balance sheet'),
(49, 'TOT.GB', 99, 'NULL', 'Total GL')
LedgerLevel 定义层次结构中的级别。父节点 059999 位于最高级别(在此示例中为 90),0 是最低级别的子节点。 我需要使用上表中的层次关系创建一个表/结构/tmp.table,如下所示:
在这里,我们可以参数化关卡数量和关卡ID。 以下是我在不考虑参数化并假设级别数 = 4 的情况下尝试过的查询。 如何在不硬编码级别数和级别 ID 的情况下实现相同的目标? 我是 SQL 的新手,对它有基本的了解。
create or alter view [dbo].[Ledgerview] as
WITH LedgerAccountstree AS
(
SELECT
ledger_key,
Ledger as CurrLedgerCode,
Ledger,
Ledger as Lvl0Code,
LedgerDescription as Lvl0Description,
cast('-' as nvarchar(12)) as Lvl1Code,
cast('-' as nvarchar(30)) as Lvl1Description,
cast('-' as nvarchar(12)) as Lvl2Code,
cast('-' as nvarchar(30)) as Lvl2Description,
cast('-' as nvarchar(12)) as Lvl3Code,
cast('-' as nvarchar(30)) as Lvl3Description,
ParentAccount,
LedgerLevel
FROM
[dbo].[LedgerAccounts]
WHERE
LedgerLevel = 50
UNION ALL
SELECT
[dbo].[LedgerAccounts].ledger_key,
LedgerAccountstree.CurrLedgerCode,
[dbo].[LedgerAccounts].Ledger,
LedgerAccountstree.Lvl0Code,
LedgerAccountstree.Lvl0Description,
case when [dbo].[LedgerAccounts].LedgerLevel = 30 then [dbo].[LedgerAccounts].Ledger else LedgerAccountstree.Lvl1Code end as Lvl1Code,
case when [dbo].[LedgerAccounts].LedgerLevel = 30 then [dbo].[LedgerAccounts].LedgerDescription else LedgerAccountstree.Lvl1Description end as Lvl1Description,
case when [dbo].[LedgerAccounts].LedgerLevel = 20 then [dbo].[LedgerAccounts].Ledger else LedgerAccountstree.Lvl2Code end as Lvl2Code,
case when [dbo].[LedgerAccounts].LedgerLevel = 20 then [dbo].[LedgerAccounts].LedgerDescription else LedgerAccountstree.Lvl2Description end as Lvl2Description,
case when [dbo].[LedgerAccounts].LedgerLevel = 0 then [dbo].[LedgerAccounts].Ledger else LedgerAccountstree.Lvl3Code end as Lvl3Code,
case when [dbo].[LedgerAccounts].LedgerLevel = 0 then [dbo].[LedgerAccounts].LedgerDescription else LedgerAccountstree.Lvl3Description end as Lvl3Description,
[dbo].[LedgerAccounts].ParentAccount,
[dbo].[LedgerAccounts].LedgerLevel
FROM
[dbo].[LedgerAccounts]
JOIN
LedgerAccountstree
ON LedgerAccountstree.Ledger = [dbo].[LedgerAccounts].[ParentAccount]
)
SELECT
ledger_key,
Ledger,
Lvl0Code +'-'+ Lvl0Description as Level0,
Lvl1Code +'-'+ Lvl1Description as Level1,
Lvl2Code +'-'+ Lvl2Description as Level2,
Lvl3Code +'-'+ Lvl3Description as Level3
FROM
LedgerAccountstree
去
【问题讨论】:
-
如果有动态数量的级别,您无法在
VIEW中执行此操作。视图只是一个虚拟表,其定义由SELECT语句定义;您不能包含变量和EXEC命令之类的内容来执行动态 SQL。 -
那么更好的选择是什么?正如我所说,我是这里的新手。
-
如果您必须获得动态结果,则需要使用存储过程之类的东西,(显然)其行为与
VIEW非常不同。
标签: sql-server dynamic parent-child hierarchy flatten