需要一些关于自加入问题的认真帮助
题
正如您可能知道的,您无法通过自连接对视图进行索引。实际上,甚至同一个表的两个连接,即使它在技术上不是自连接。微软的几个人想出了一个解决办法。但是太复杂了,看不懂!!!
问题的解决方案在这里: http://jmkehayias.blogspot.com/2008/12/creating-indexed-view-with-self-join.html
我想要应用此工作的视图是:
create VIEW vw_lookup_test
WITH SCHEMABINDING
AS
select
count_big(*) as [count_all],
awc_txt,
city_nm,
str_nm,
stru_no,
o.circt_cstdn_nm [owner],
t.circt_cstdn_nm [tech],
dvc.circt_nm,
data_orgtn_yr
from
((dbo.dvc
join dbo.circt
on dvc.circt_nm = circt.circt_nm)
join dbo.circt_cstdn o
on circt.circt_cstdn_user_id = o.circt_cstdn_user_id)
join dbo.circt_cstdn t
on dvc.circt_cstdn_user_id = t.circt_cstdn_user_id
group by
awc_txt,
city_nm,
str_nm,
stru_no,
o.circt_cstdn_nm,
t.circt_cstdn_nm,
dvc.circt_nm,
data_orgtn_yr
go
任何帮助将不胜感激!
非常感谢!
编辑 :所以我发现这也行得通。请注意,我在第一个索引视图中加入表一次,并在第二个非索引视图中加入第二次。
alter VIEW vw_lookup_owner_test2
WITH SCHEMABINDING
AS
select
count_big(*) as [countAll],
awc_txt,
city_nm,
str_nm,
stru_no,
dvc.circt_nm,
circt_cstdn_nm,
data_orgtn_yr,
dvc.circt_cstdn_user_id
from dbo.dvc
join dbo.circt
on dvc.circt_nm = circt.circt_nm
join dbo.circt_cstdn o
on circt.circt_cstdn_user_id = o.circt_cstdn_user_id
group by
awc_txt,
city_nm,
str_nm,
stru_no,
dvc.circt_nm,
circt_cstdn_nm,
data_orgtn_yr,
dvc.circt_cstdn_user_id
go
和
CREATE UNIQUE CLUSTERED INDEX [idx_vw_lookup_owner2_test1] ON [dbo].[vw_lookup_owner_test2]
(
[awc_txt] ASC,
[city_nm] ASC,
[str_nm] ASC,
[stru_no] ASC,
[circt_nm] ASC,
[circt_cstdn_nm] ASC,
[data_orgtn_yr] ASC,
[circt_cstdn_user_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
和
create view vw_lookup_dvc_loc
as
select
awc_txt,
city_nm,
str_nm,
stru_no,
circt_nm,
o.circt_cstdn_nm as [owner],
--o.circt_cstdn_user_id,
t.circt_cstdn_nm as tech,
data_orgtn_yr
from vw_lookup_owner_test2 o With (NOEXPAND)
join circt_cstdn t
on o.circt_cstdn_user_id = t.circt_cstdn_user_id
group by
awc_txt,
city_nm,
str_nm,
stru_no,
circt_nm,
o.circt_cstdn_nm,
data_orgtn_yr,
t.circt_cstdn_nm
--o.circt_cstdn_user_id
然后我可以根据需要在第一个视图上创建附加索引。我不确定这个解决方案(或解决该问题的方法)是否真的会加快性能,但我会让您知道。
解决方案
这是我从博客文章中得到的内容
假设您想在 dbo.circt_cstdn 上加入 2 次,即你想要类似的东西
owner tech rowA a.nm b.nm ...
不是将值放入 2 列,而是将其放入 2 行(上面每行 2 行),并添加一个附加列来说明哪一行对应哪一列。请注意,第 1.1 行和第 1.2 行具有相同的数据(名称和列除外)
name for row1.1 nm owner row1.2 nm tech ...
然后,您以所有者和技术人员的名称列的最大值为中心。注意 - 最大函数只是为了欺骗枢轴(需要一些汇总函数),如果只有一个记录所有者Tech Row1 NM NM NM NM ...
现在,如果我们为您的查询执行此操作
创建一个表d,像这样
i 1 2
与此交叉连接查询的第一部分
SELECT count_big(*) as [count_all], awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr FROM dbo.dvc INNER JOIN dbo.circt on dvc.circt_nm = circt.circt_nm CROSS JOIN dbo.d GROUP BY awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, d.i
现在,如果 D.i 为 1,则使用所有者行;如果 D.i 为 2,则使用技术
SELECT count_big(*) as [count_all], awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, Case WHEN d.i = 1 THEN 'Owner' WHEN d.i = 2 THEN 'Tech' END FROM dbo.dvc INNER JOIN dbo.circt on dvc.circt_nm = circt.circt_nm CROSS JOIN dbo.d GROUP BY awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, Case WHEN d.i = 1 THEN 'Owner' WHEN d.i = 2 THEN 'Tech' END
现在添加 nm 列。要获取名称,如果它是所有者行 (d.i = 1),请使用 circt 加入 circt_cstdn;如果它是技术行 (d.i = 2),请加入 dvc。注意 - 我在这里尝试了一种快捷方式,将其放入连接条件中。如果它不起作用,请尝试博客文章方式(在 circt.circt_cstdn_user_id 上进行连接 或者 dvc.circt_cstdn_user_id,然后使用WHERE子句过滤掉)
SELECT count_big(*) as [count_all], awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, Case WHEN d.i = 1 THEN 'Owner' WHEN d.i = 2 THEN 'Tech' END as PersonType, circt_cstdn_nm FROM dbo.dvc INNER JOIN dbo.circt on dvc.circt_nm = circt.circt_nm CROSS JOIN dbo.d INNER JOIN dbo.circt_cstdn on circt_cstdn_user_id = CASE WHEN d.i = 1 THEN circt.circt_cstdn_user_id WHEN d.i = 2 THEN dvc.circt_cstdn_user_id END GROUP BY awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, Case WHEN d.i = 1 THEN 'Owner' WHEN d.i = 2 THEN 'Tech' END, circt_cstdn_nm
使用它创建一个视图并创建索引
create VIEW vw_lookup_test_imed WITH SCHEMABINDING AS <<query above>> GO spell to create INDEX
现在,您可以通过 PIVOT 将 PersonType 列转换为 Owner 和 Tech 列
SELECT count_all, awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, [Owner], [Tech] FROM ( SELECT count_all, awc_txt, city_nm, str_nm, stru_no, dvc.circt_nm, data_orgtn_yr, PersonType, circt_cstdn_nm FROM dbo.vw_lookup_test_imed WITH (NOEXPAND) ) src PIVOT ( MAX(circt_cstdn_nm) FOR PersonType IN ([Owner], [Tech]) ) pvt
如果存在语法错误(肯定有很多错误,因为我现在无法访问数据库),请告诉我。
其他提示
我认为这JOIN语法是可怕的和源自MS访问。啊。 我建议你使用:
select
count_big(*) as [count_all],
awc_txt,
city_nm,
str_nm,
stru_no,
o.circt_cstdn_nm [owner],
t.circt_cstdn_nm [tech],
dvc.circt_nm,
data_orgtn_yr
-- HERE
from dbo.dvc
join dbo.circt on (dvc.circt_nm = circt.circt_nm)
join dbo.circt_cstdn o on (circt.circt_cstdn_user_id = o.circt_cstdn_user_id)
join dbo.circt_cstdn t on (dvc.circt_cstdn_user_id = t.circt_cstdn_user_id)
group by
awc_txt,
city_nm,
str_nm,
stru_no,
o.circt_cstdn_nm,
t.circt_cstdn_nm,
dvc.circt_nm,
data_orgtn_yr
这句法更干净,更容易理解和SQL Server,火鸟,甲骨文,MySQL和其他多是公认的。 现在你可以看到更好的“表”之间的关系。 当您加入相同的“表”两次或更多次,你需要别名每一个。在一行“circt_cstdn”的别名是“O”。上的其他线, “circt_cstdn” 的别名为 “T”。
我建议使用LEFT的JOIN或INNER JOIN代替JOIN。