2013-10-29 20 views
1

可能有更好的方法來創建這些視圖。我有限的SQL經驗,所以這是我設計它的方式,我希望你們中的一些SQL大師可以指出我更有效的方向。使用多個子查詢的慢速SQL視圖

我基本上在我的視圖3個表(有時4),這裏是必不可少的結構:

Table USER 
USER_ID | EMAIL | PASSWORD | CREATED_DATE 

(指標:USER_ID)

Table USER_META 
ID | USER_ID | NAME | VALUE 

(指標:ID,USER_ID,NAME )

Table USER_SCORES 
ID | USER_ID | GAME_ID | SCORE | CREATED_DATE 

(指標:ID,USER_ID)

所有表都使用第一個ID列作爲自動增量主鍵。

第二個表「USER_META」是我把所有的聯繫人信息和其他雜項。首先是名字,姓氏,街道,城市等 - 根據用戶,這可能是4項或140,這就是爲什麼我用這個表,而不是在我的用戶表中有150列。

對於報表,搜索和編輯我需要從USER_META約20個值,所以我的看法是這樣的:

View V_USR_META 
select USER_ID,EMAIL, 
(select VALUE from USER_META 
    where NAME = 'FIRST_NAME' and USER_ID = u.USER_ID) as first_name, 
(select VALUE from USER_META 
    where NAME = 'LAST_NAME' and USER_ID = u.USER_ID) as last_name, 
(select VALUE from USER_META 
    where NAME = 'CITY' and USER_ID = u.USER_ID) as city, 
(select VALUE from USER_META 
    where NAME = 'STATE' and USER_ID = u.USER_ID) as state, 
(select VALUE from USER_META 
    where NAME = 'ZIP' and USER_ID = u.USER_ID) as zip, 
    /* 10 more selects for different meta values here */ 
(select max(SCORE) from USER_SCORES 
    where USER_ID = u.USER_ID) as high_score, 
(select top (1) CREATED_DATE from USER_SCORES 
    where USER_ID = u.USER_ID 
    order by id desc) as last_game 
from USER u 

這GET的很慢,而且有實際上更多的子查詢,這是隻是爲了說明查詢。我還必須查詢其他幾個表來獲取其他表格。有關用戶的信息。

我使用的視圖爲用戶搜索時,搜索中使用的姓名或用戶ID或電子郵件或分數等,我還用它來填充用戶信息畫面時,我提出在一個地方的所有數據。

所以 - 有沒有更好的方式來寫的看法?

回答

1

所有這些相關子查詢的另一種方法是使用maxcase

select u.USER_ID, 
     u.EMAIL, 
     max(case when um.name = 'FIRST_NAME' then um.value end) first_name, 
     max(case when um.name = 'LAST_NAME' then um.value end) last_name 
     ... 
from USER u 
     left join USER_META um 
       on u.user_id = um.user_id 
group by u.user_id, u.email 

然後,你可以添加user_scores結果:

select u.USER_ID, 
     u.EMAIL, 
     max(case when um.name = 'FIRST_NAME' then um.value end) first_name, 
     max(case when um.name = 'LAST_NAME' then um.value end) last_name 
     ..., 
     max(us.score) maxscore, 
     max(us.created_date) maxcreateddate 
from USER u 
     left join USER_META um 
       on u.user_id = um.user_id 
     left join USER_SCORES us 
       on u.user_id = us.user_id 
group by u.user_id, u.email 
0
WITH Meta AS (
    SELECT USER_ID 
      ,FIRST_NAME 
      ,LAST_NAME 
      ,CITY 
      ,STATE 
      ,ZIP 
    FROM USER_META 
    PIVOT (
     MAX(VALUE) FOR NAME IN (FIRST_NAME, LAST_NAME, CITY, STATE, ZIP) 
    ) AS p 
) 
,MaxScores AS (
    SELECT USER_ID 
      ,MAX(SCORE) AS Score 
    FROM USER_SCORES 
    GROUP BY USER_ID 
) 
,LastGames AS (
    SELECT USER_ID 
      ,MAX(CREATED_DATE) AS GameDate 
    FROM USER_SCORES 
    GROUP BY USER_ID 
) 
SELECT USER.USER_ID 
     ,USER.EMAIL 
     ,Meta.FIRST_NAME 
     ,Meta.LAST_NAME 
     ,Meta.CITY 
     ,Meta.STATE 
     ,Meta.ZIP 
     ,MaxScores.Score 
     ,LastGames.GameDate 
FROM USER 
    INNER JOIN Meta 
     ON USER.USER_ID = Meta.USER_ID 
    LEFT JOIN MaxScores 
     ON USER.USER_ID = MaxScores.USER_ID 
    LEFT JOIN LastGames 
     ON USER.USER_ID = LastGames.USER_ID