こんにちは42,400行を保持するテーブルがあります。これはSQL標準ではかなり小さいです。スモールセルフ自己結合クエリ
テーブルは施設の場所を保持し、親子関係として設計されています。
CREATE TABLE [dbo].[Location](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ParentLocationId] [int] NULL,
[Description] [varchar](100) NOT NULL,
[LocationTypeId] [int] NOT NULL,
[IsDeleted] [bit] NOT NULL,
CONSTRAINT [pk_Location] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
これには、5行のLocationTypeテーブルに対する外部キーがあります。
ALTER TABLE [dbo].[Location] WITH CHECK ADD CONSTRAINT [fk_location_locationtype] FOREIGN KEY([LocationTypeId])
REFERENCES [ref].[LocationType] ([Id])
GO
また、自己への自己参加もあります。
ALTER TABLE [dbo].[Location] WITH CHECK ADD CONSTRAINT [fk_LocationLocation] FOREIGN KEY([ParentLocationId])
REFERENCES [dbo].[Location] ([Id])
GO
親は多くの子を持つことができます。しかし、私たちは一定数の位置レベルを持っています。そして、ロケーション情報はたくさん問い合わせられます。
私は場所データを取得するためのビューを実装しました。
これはちょっと長いので、一番下にありますが、考え方は、耳のレベルの行を設定してから、子に参加して、結合を行い、結果セットを返すことです。例えば
:
選択する場所所在地のレベル= 1(ルート) 次に 場所レベルが2であり、それの両親への参加を選択。 Then 場所レベル3を選択して、その親とその親に参加します。
これはパフォーマンス上の問題と思われます。 、場所ごとの行である私が探しています結果を、達成するためのより良い方法は、最初の行がルートノードである...
あります... 第二は、それが最初の子だと、ルートである 第三ルートは
は...それは第二子だと特定の場所での選択を行うための一例である:
SELECT
l1.Id as LocationId,
l1.LocationTypeId,
lt.DisplayName,
l1.ParentLocationId,
l1.Description AS thisLocationName,
l1.IsDeleted,
l1.Description AS Level1,
NULL AS Level2,
NULL AS Level3,
NULL AS Level4,
NULL AS Level5,
NULL AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].Location l1
INNER JOIN ref.LocationType lt
ON lt.Id = l1.LocationTypeId
AND lt.level = 1
UNION
SELECT
l2.Id AS LocationId,
l2.LocationTypeId,
lt.DisplayName,
l2.ParentLocationId,
l2.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
NULL AS Level3,
NULL AS Level4,
NULL AS Level5,
NULL AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].Location l1
INNER JOIN [dbo].Location l2
ON l2.ParentLocationId = l1.Id
INNER JOIN ref.LocationType lt
ON lt.Id = l2.LocationTypeId
AND lt.level = 2
UNION
SELECT
l3.Id AS LocationId,
l3.LocationTypeId,
lt.DisplayName,
l3.ParentLocationId,
l3.Description AS thisLocationName,
l1.IsDeleted | l2.IsDeleted | l2.IsDeleted,
l1.Description AS Level1,
l2.Description AS Level2,
l3.Description AS Level3,
NULL AS Level4,
NULL AS Level5,
NULL AS Level6,
NULL AS Level7,
NULL AS Level8,
NULL AS Level9,
NULL AS Level10
FROM [dbo].Location l1
INNER JOIN [dbo].Location l2
ON l2.ParentLocationId = l1.Id
INNER JOIN [dbo].Location l3
ON l3.ParentLocationId = l2.Id
INNER JOIN ref.LocationType lt
ON lt.Id = l3.LocationTypeId
AND lt.level = 3
UNION
.... (This occurs for 10 levels)
ここでは、テーブルのように、デモデータがあります。
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(1, NULL, 'A Building', 1)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(2, 1, '1st Floor', 2)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(3, 1, '2nd Floor', 2)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(4, 1, '3rd Floor', 2)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(5, 1, '4th Floor', 2)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(6, 1, 'Boardroom', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(7, 1, 'Main Office', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(8, 1, 'Directors Office', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(9, 1, 'Kitchen', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(10, 2, 'Office', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(11, 2, 'Meeting Room', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(12, 2, 'Kitchen', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(13, 2, 'Gents WC', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(14, 2, 'Ladies WC', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(15, 3, 'Office 1', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(16, 3, 'Office 2', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(17, 3, 'Office 3', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(18, 3, 'Office 4', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(19, 3, 'Meeting Room', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(20, 3, 'Staff Room', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(21, 4, 'Small Office', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(22, 4, 'Medium', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(23, 4, 'Large Office', 3)
INSERT INTO Location
(Id, ParentLocationId, Description, LocationTypeId)
VALUES
(24, 4, 'Meeting Room', 3)
は私がしようとしたCTEのバージョンは、以下の推奨:
CREATE VIEW [dbo].[vwLocations3]
WITH SchemaBinding
AS
with h as (
select l.Id, l.ParentLocationId, l.Description, l.LocationTypeId, l.IsDeleted
, convert(varchar(100), null) level2
, convert(varchar(100), null) level3
, convert(varchar(100), null) level4
, convert(varchar(100), null) level5
, convert(varchar(100), null) level6
, convert(varchar(100), null) level7
, convert(varchar(100), null) level8
, convert(varchar(100), null) level9
from dbo.Location l
where ParentLocationId IS NULL
UNION ALL
select l.Id, l.ParentLocationId, l.Description, l.LocationTypeId, l.IsDeleted
, case when l.LocationTypeId = 2 then l.Description when l.LocationTypeId > 2 then h.Description end level2
, case when l.LocationTypeId = 3 then l.Description when l.LocationTypeId > 3 then h.Description end level3
, case when l.LocationTypeId = 4 then l.Description when l.LocationTypeId > 4 then h.Description end level4
, case when l.LocationTypeId = 5 then l.Description when l.LocationTypeId > 5 then h.Description end level5
, case when l.LocationTypeId = 6 then l.Description when l.LocationTypeId > 6 then h.Description end level6
, case when l.LocationTypeId = 7 then l.Description when l.LocationTypeId > 7 then h.Description end level7
, case when l.LocationTypeId = 8 then l.Description when l.LocationTypeId > 8 then h.Description end level8
, case when l.LocationTypeId = 9 then l.Description when l.LocationTypeId > 9 then h.Description end level9
from h
inner join dbo.Location l on l.ParentLocationId = h.id
)
SELECT
h.Id AS LocationId,
h.LocationTypeId,
lt.DisplayName,
h.ParentLocationId,
h.Description AS thisLocationName,
--h.Level1,
h.Level2,
h.Level3,
h.Level4,
h.Level5,
h.Level6,
h.Level7,
h.Level8,
h.Level9
--cte.Level10
FROM h
INNER JOIN ref.LocationType lt
ON lt.Id = h.LocationTypeId
しかし、これは1,500msでの選択を返しています。
UNIONは、UNION ALL –
おかげ@Used_By_Alreadyより遅い、重複を削除します。 – Craig
あなたの質問にサンプルデータを追加します(必要な10レベルはすべてではなく、ほんの数行ではありません)。そのデータサンプルから期待される結果を追加します。 –