2016-09-16 58 views
1

我在數據庫中有四個表:City,User,CityRating,CityGreeting。 CityRating表的UserID和CityID作爲PK,這些都是FK的USer和City表。 CityGreeting表沒有PK,但具有用戶ID和城市ID作爲FK(想法是用戶可以根據需要多次迎接城市,但只對一個城市評分一次)。多個連接,在一張桌子上的平均數,在另一個數上

我想寫一個查詢,將整體回報的平均等級的城市,以及時代的特定用戶歡迎的城市:

select City.CityID, City.CityName, City.CityStateOrProvince, 
ROUND(AVG(Cast(RateCity.Rating as float)), 2) as AverageRating, 
(select COUNT(HelloCity.CityID) from HelloCity where HelloCity.UserID like '<guid>') as TimesVisited 
from City 
right join RateCity 
on City.CityID = RateCity.CityID 
right join HelloCity 
on City.CityID = HelloCity.CityID 
group by City.CityID, City.CityName, 
City.CityStateOrProvince, City.CityCountry, City.CityImageUri 

即使我能得到這個作爲工作預計(目前不是)我覺得它真的很混亂。就最佳實踐而言,寫兩個查詢會更好嗎?這個操作將在api中執行,不確定在編寫兩個單獨的查詢時性能會更好,還是像這樣複雜的查詢。對此的任何見解或如何讓查詢按預期工作?

***編輯:添加圖片澄清:平均評分是所有評分的用戶的平均值,TimesVisited是一個特定用戶訪問該城市的次數。

Added picture to clarify: Average Rating is the average of all users who rated, and TimesVisited is the amount of times one specific user has visited the city.

+0

什麼你是否像使用UserId一樣使用?你不應該在說UserID =和City.CityId = HelloCity.CityId嗎? – MacWise

+0

您可以添加樣本數據和預期結果 –

+0

我添加了一張圖片來說明結果 - 圖片中唯一不正確的是TimesVisited列 - 它應該顯示特定用戶訪問過每個城市的次數 – KateMak

回答

3

我相信你需要從city彙總表,除了單獨爲使其正常工作:

select c.*, rc.AverageRating, coalesce(hc.TimesVisited, 0) as TimesVisited 
from City c join 
    (select CityId, ROUND(AVG(Cast(RateCity.Rating as float)), 2) as AverageRating 
     from RateCity rc 
     group by CityId 
    ) rc 
    on c.CityID = rc.CityID left join 
    (select CityId, count(*) as TimesVisited 
     from HelloCity hc 
     where hc.UserID like '<guid>' 
     group by CityId 
    ) hc 
    on c.CityId = hc.CityId; 

注:

  • 表的別名使查詢更容易寫和讀。
  • 我懷疑你的意思是right join。這意味着在其他兩個表格中有CityId s不在City中。
  • 通過爲每個其他表進行聚合,您不需要外部查詢中的聚合。
  • 我的確認爲HelloCity表需要left join,因爲不是所有的城市都可能有訪問者。
  • 對於RateCity表,您可能還需要left join表,如果不是所有城市都有評分。
+0

這真是令人印象深刻。謝謝你。很好的解釋,以及 – KateMak

+0

我希望詢問有關查詢的語法 - 我看到c是城市的別名 - 你能解釋括號中的部分在做什麼嗎?它是否只是獲得由括號中的select所定義的別名的「列」? – KateMak

+1

@KateMak。 。 。括號中的部分是子查詢。 –

2

你爲什麼不每個CTE使用CTE,然後做的各個部分,它有助於打破它,而不是試圖混搭在一起的一堆聯接:例如:

DECLARE @userId VARCHAR(10) = 'userid1' ; 

WITH 

CITY_RATING_CTE (cityId, AverageRating) AS 
    (SELECT cityId, 
      AVG(Rating) AS rating 
    FROM RateCity 
    GROUP BY cityId), 

TIMES_VISITED_CTE AS 
    (SELECT cityId, 
      count(*) AS TimesVisited 
    FROM HelloCity 
    WHERE UserId = @userId 
    GROUP BY cityId) 
SELECT c.CityId, 
     c.CityName, 
     c.CityStateOrProvince, 
     c.CityImageUri, 
     cr.AverageRating, 
     tv.TimesVisited 
FROM City c 
JOIN CITY_RATING_CTE cr ON cr.cityId = c.CityId 
JOIN TIMES_VISITED_CTE tv ON cr.cityId = cr.cityId; 
+0

在查詢中添加了userid – MacWise

相關問題