2010-04-21 63 views
1

爲了簡化故事,我正在構建自我學習橫幅管理系統。根據銷售/展示率顯示橫幅時,用戶將能夠將這些橫幅插入到他們的網站。幫助複雜的sql查詢

我有4個表

Banners 
bannerID  int 
bannerImage varchar.... 

SmartBanners 
smartBannerID  int 
smartBannerArrayID int 
bannerID   int 
impressionsCount int 
visibility   tinyint (percents) 

SmartBannerArrays 
smartBannerArrayID int 
userID    int 

Statistics 
bannerID   int 
saleAmountPerDay decimal... 

每天晚上,我需要根據整個SmartBannerArray同一用戶有可能產生新的每個SmartBanner「知名度」。所以我需要在SmartBannerArray中獲得每個bannerID的展示次數和銷售額總和。

所有在我腦海中是使用雙光標,一個將循環認爲SmartBannerArrays獲得所需值的展示和銷售,然後內環將訪問每個SmartBanner並改變它是一個基於 (銷售「知名度」的百分比之和/次數)/(sumOfSales/sumOfImpressions)* 100

希望你得到的圖片...

是否有任何其他的方式來設計更好的表或不使用雙光標來避免服務器超載?

更多信息 每個銷售寫入統計表,字段更新,因爲我需要每個橫幅,而不是每個銷售每日總和。用戶創建BannerArray,選擇他想要推廣的產品。他選擇的每個產品都寫在Banners表中,並帶有適當的圖像和其他信息。 SmartBanners表存儲bannerID以便統計表,而BannerArray表將這組橫幅分配給特定用戶。

+0

如果你真的在設計改進之後,你將不得不進一步描述你試圖建模的過程(統計表是如何填充的,smartbanners和橫幅之間的關係是什麼,smartbannerarrays是什麼等等。 ..)。可以做出假設,但基於假設的分析不是一件好事。 – Unreason 2010-04-21 13:38:27

+0

這樣做,如果你仍然有一個問題,自由地下午我... – eugeneK 2010-04-21 13:48:01

回答

2

圖片不太清楚。爲什麼要使用遊標?這有什麼問題?

SELECT SUM(saleAmountPerDay)/SUM(impressionsCount) 
FROM SmartBanners sb  INNER JOIN 
    SmartBannerArrays sba ON sb.smartBannerArrayID = sba.smartBannerArrayID INNER JOIN 
    Statistics ss   ON sb.bannerID = ss.bannerID 
GROUP BY smartBannerArrayID 

哪個可以用作子查詢直接計算'可見性'。

EDIT2: 龍虎鬥原則(SQL沒有優化),爲什麼不:

UPDATE SmartBanners 
SET visibility = 
    ROUND(100. * 
    (
    SELECT SUM(saleAmountPerDay)/SUM(impressionsCount) 
    FROM SmartBanners sb  INNER JOIN 
     Statistics ss   ON sb.bannerID = ss.bannerID 
    WHERE sb.smartBannerID = SmartBAnners.smartBannerID 
    )/
    (
    SELECT SUM(saleAmountPerDay)/SUM(impressionsCount) 
    FROM SmartBanners sb  INNER JOIN 
     SmartBannerArrays sba ON sb.smartBannerArrayID = sba.smartBannerArrayID INNER JOIN 
     Statistics ss   ON sb.bannerID = ss.bannerID 
    WHERE sb.smartBannerArrayID = SmartBAnners.smartBannerArrayID 
    )) 
如果你想避免光標

此外,不要忘記 - 如果這些數據不會經常更新(統計表更新的頻率是多少?我想你會定期從一些日誌中更新它),如果您希望最大化讀取你可能會考慮觸發器的性能。

EDIT3: 在MS SQL你也可以使用OVER條款,只是一個簡單的例子

SELECT 
     SUM(saleAmountPerDay) OVER(PARTITION BY BannerID) AS 'TotalSalesByBanner', 
     SUM(impressionsCount) OVER(PARTITION BY BannerID) AS 'TotalImpressionsByBanner', 
     SUM(saleAmountPerDay) OVER(PARTITION BY smartBannerArrayID) AS 'TotalSalesByArray', 
     SUM(impressionsCount) OVER(PARTITION BY smartBannerArrayID) AS 'TotalImpressionsByBanner'  
FROM 
     SmartBanners sb INNER JOIN 
     Statistics ss ON sb.bannerID = ss.bannerID 
GROUP BY 
     SmartBannerID 

這個SQL沒有進行測試。

+0

我仍然需要有遊標設置「知名度」,否則每次新的橫幅將生成這個巨大的查詢將運行... 謝謝用於保存一個遊標.... – eugeneK 2010-04-21 13:01:58

+0

如果您發現有用的東西,隨時upvote。現在,我編輯了答案。如果您希望查詢的確切示例,可以進一步解釋(編輯您的問題)SmartBanners和Banners表之間的關係? – Unreason 2010-04-21 13:32:34

+0

問題是我需要更新每個橫幅,從而循環思考它們。想一想,我有很多統計數據,很多橫幅和很多橫幅數組。我需要更新每個橫幅的可見性,所以下一次用戶訪問陣列時,它會顯示最賣出的產品。 – eugeneK 2010-04-21 13:41:27

1

在許多情況下,使用派生表可以避免使用遊標。可以找到使用它們的介紹here

+0

感謝,閱讀它 – eugeneK 2010-04-21 14:42:41

0

我認爲你問的是正確的問題,那就是:有什麼方法可以設計更好的表格嗎?我的建議是:不用擔心服務器負載過重,如果每天只運行一次查詢,這沒什麼大不了的。擔心更多關於可理解的結構。

這個怎麼樣:

Banners 
------- 
BannerID 
UserID 
BannerImage 
BannerVisibility // A denormalized value that you calculate once a day 

Banner_Sales 
------------ 
BannerID 
Date 
SalesAmt 

Banner_Impressions 
------------------ 
BannerID 
Date 
Impressions 

你並不需要一個SmartBannerArray - 或光標 - 總結銷售和曝光。只需使用一個SQL總和:

SELECT SUM(bs.SalesAmt) AS SALES, SUM(bi.Impressions) AS IMPRESSIONS, 
    SUM(bs.SalesAmt)/SUM(bi.Impressions) AS RATIO 
FROM Banners b 
JOIN Banner_Sales bs 
JOIN Banner_Impressions bi 
WHERE b.UserID = ? // For total sales/impressions for a user 

替代

WHERE b.BannerID = ? // For total sales/impressions for a banner 

祝你好運!

P.S. tinyint的是整數,而不是百分比。你需要一倍。 :)

+0

他選擇存儲百分比作爲整數,在問題公式中乘以100.如果這樣的精度令人滿意,沒有問題與tinyints。 – Unreason 2010-04-21 13:35:32

+0

我需要SmartBannerArray,因爲我擁有的廣告模塊會爲每個用戶顯示一組橫幅。 ++謝謝無理由,我不需要更多 – eugeneK 2010-04-21 13:36:30