Как переписать CROSS APPLY в INNER JOIN, чтобы сделать индексированное представление - PullRequest
4 голосов
/ 03 ноября 2010

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

Name     Orders
'John'   New Hat, New Book, New Phone
'Marry'  NULL

Мне нужно индексировать представление, но вы не можете сделать это, если запрос SELECT в представлении имеет APPLY и / или подзапросы. Можно ли перевести это представление в индексированное представление?

create table Customers (CustomerId int, CustomerName VARCHAR(100))
create table Orders    (CustomerId int, OrderName VARCHAR(100))

insert into Customers  (CustomerId, CustomerName) select 1, 'John' union all select 2, 'Marry'
insert into Orders     (CustomerId, OrderName)    select 1, 'New Hat' union all select 1, 'New Book' union all select 1, 'New Phone'
go

create view OrderView as 
select c.CustomerName, x.OrderNames        
from Customers c            
cross apply (select stuff((select ',' + OrderName from Orders o 
      where o.CustomerId = c.CustomerId for xml path('')),1,1,'') 
      as OrderNames) x
go

Ответы [ 2 ]

11 голосов
/ 03 ноября 2010

Вы не можете сделать это представление проиндексированным.

По сути, у вас есть агрегатная функция (замаскированная как CROSS APPLY).

Единственными агрегатными функциями, разрешенными в индексированном представлении, являются COUNT_BIG и SUM, поскольку они распространяются на сложение и вычитание набора, то есть SUM(a UNION ALL b) = SUM(a) + SUM(b), SUM(a EXCEPT ALL b) = SUM(a) - SUM(b).

Это свойство необходимо для того, чтобы индекс мог обслуживаться.

Когда новая запись вставляется, обновляется или удаляется из базовой таблицы, не требуется повторная оценка всего представления: значение новой записи просто добавляется или вычитается из совокупного значения.

Кроме того, COUNT_BIG также должен быть частью представления, чтобы отслеживать удаление записей (когда оно становится 0, запись должна быть удалена из индекса представления).

0 голосов
/ 06 марта 2019

Если вы используете внутреннее соединение с 1 = 1, оно удовлетворяет условию и разрешает соединение.

Выбрать * От х внутреннее соединение у 1 = 1

...