Question

Eh bien comme vous le savez, vous ne pouvez pas indexer une vue avec une jointure réflexive. Et bien en fait même deux jointures de la même table, même si ce n'est pas techniquement une jointure réflexive. Un couple de gars de Microsoft est venu avec un travail autour. Mais il est tellement compliqué que je ne le comprends pas !!!

La solution au problème est ici: http://jmkehayias.blogspot.com/2008/12/creating-indexed-view-with-self-join.html

Le point de vue que je veux appliquer ce travail autour de est:

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

Toute aide serait grandement aprécié !!!

Merci beaucoup à l'avance!

EDIT: Je trouve que ce sera aussi le travail. Notez que je me joins à la table une fois dans la première vue indexée, et la deuxième fois en deuxième Teh vue non indexée.

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

et

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

et

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

Je peux alors créer additon index sur la première vue que je souhaite. Je ne sais pas si cette solution (ou la solution de contournement pour cette question) sera effectivement accélérer preformance, mais je vais vous laisser savoir.

Était-ce utile?

La solution

Voici ce que je suis de la blogpost

  • Soit s dire que vous voulez joindre 2 fois sur dbo.circt_cstdn vous voulez dire quelque chose comme

             owner       tech
    rowA     a.nm        b.nm
    ...
    
  • Au lieu d'obtenir les valeurs dans 2 colonnes vous en 2 lignes (2 pour chaque ligne ci-dessus) et ajouter une colonne supplémentaire pour dire quelle ligne est pour quelle colonne. Notez que la ligne 1.1 et la ligne 1.2 ont les mêmes données (à l'exception du nom et des colonnes)

             name   for
    row1.1   nm     owner
    row1.2   nm     tech
    ...
    
  • Ensuite, vous pivoter sur max de la colonne de nom pour le propriétaire et technologie. Remarque - la fonction max est juste pour tromper le PIVOT (qui nécessite une certaine fonction d'agrégation), vous pouvez utiliser une fonction d'agrégation qui retourne la même valeur s'il n'y a qu'un seul enregistrement       tech propriétaire row1 nm nm ...

Maintenant, si nous le faisons pour votre requête

  1. Créer une table d, comme celui-ci

     i
     1
     2
    
  2. Cross se joindre à la première partie de votre requête avec cette

    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
    
  3. Maintenant, nous allons utiliser la ligne pour le propriétaire si D.i est 1, et la technologie si D.i est 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  
    
  4. Maintenant, ajoutez la colonne nm. Pour obtenir le nom que vous rejoignez circt_cstdn avec circt si elle est une ligne de propriétaire (d.i = 1), et avec DVC si elle est une ligne de technologie (d.i = 2). Remarque - J'ai essayé un raccourci ici en mettant cela dans la condition de jointure. Si cela ne fonctionne pas essayer la voie post blog (faire une jointure sur circt.circt_cstdn_user_id ou dvc.circt_cstdn_user_id, puis utilisez la clause WHERE pour filtrer)

    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
    
  5. Créer une vue à l'aide et que créer l'index

    create VIEW vw_lookup_test_imed
    WITH SCHEMABINDING 
    AS
        <<query above>>  
    GO
    
    spell to create INDEX
    
  6. Maintenant, vous PIVOT pour convertir la colonne PersonType aux colonnes et le propriétaire 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 
    

S'il y a des erreurs de syntaxe (il y a forcément beaucoup parce que je n'ai pas accès à une base de données en ce moment) faites-moi savoir.

Autres conseils

Je pense que cette syntaxe JOIN est horrible et origine de MS Access. Pouah. Je vous recommande d'utiliser:

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 

Cette syntaxe est plus propre, plus compréhensible et est reconnu dans SQL Server, Firebird, Oracle, MySQL et d'autres beaucoup. Maintenant, vous pouvez voir mieux les relations entre les « tables ». Lorsque vous rejoignez la même « table » deux fois ou plus, vous devez alias chacun. Sur une ligne « circt_cstdn » est Lissé comme « o ». Sur une autre ligne, "circt_cstdn" est Lissé comme "t".

Je recommande l'utilisation de LEFT JOIN ou INNER JOIN à la place JOIN.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top