Come riscrivere CROSS APPLY per join interno per rendere la vista indicizzata
-
28-09-2019 - |
Domanda
In un thread separato ho avuto un esempio di lavoro su come tradurre il mio memorizzata proc ad una visione, che conterrà i nomi dei clienti agli ordini mappatura, dove gli ordini sono elenchi separati da virgole di ordini, tra cui NULL per ordini. Così, per la tabella che segue, ho bisogno seguenti opzioni da visualizzare nella vista:
Name Orders
'John' New Hat, New Book, New Phone
'Marry' NULL
Ho bisogno di indicizzare la vista, ma non puoi farlo se la query SELECT all'interno di una vista è applicare e / o sottoquery. E 'possibile tradurre questo in vista di una vista indicizzata?
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
Soluzione
Non è possibile fare questa vista indicizzata.
In sostanza, si stanno avendo una funzione di aggregazione qui (travestito da CROSS APPLY
).
Le funzioni solo aggregazione consentite in una vista indicizzata sono COUNT_BIG
e SUM
, perché distribuiscono su set addizione e sottrazione, cioè SUM(a UNION ALL b) = SUM(a) + SUM(b)
, SUM(a EXCEPT ALL b) = SUM(a) - SUM(b)
.
Questa proprietà è obbligatoria per l'indice di essere gestibile.
Quando si inserisce un nuovo record, aggiornata o cancellata dalla tabella sottostante, l'intera vista non deve essere rivalutati:. Il valore del nuovo record viene aggiunto o sottratto dal valore complessivo
In aggiunta, un COUNT_BIG
dovrebbe essere una parte della vista, nonché, per monitorare le eliminazioni di record (quando diventa 0
, un record deve essere eliminato dalla indice di vista).
Altri suggerimenti
Se si utilizza un inner join con 1 = 1 è in grado di soddisfare la condizione e di consentire il join.
Seleziona * da x inner join y su 1 = 1