2012-08-14 62 views
0

這裏限制的結果是我的情況的工作流程:SQL - 加入3個表,但基於第一臺

我有一個網站,允許註冊用戶從本地獎品贊助商獎品註冊(即:例如,可能有一個頁面將必勝客作爲贊助商,而註冊/認證的用戶只需點擊「輸入繪圖」,一旦他們做了,他們就不能再次點擊它。

這裏有3個表:

  1. BD_Listing(該表是用於獎品贊助商,並且包括基本列如ListingID,標題,ContactPerson,電郵,獎)

  2. 用戶(此表適用於網站上的註冊用戶,包括用戶名,名字,姓氏,電子郵件等)

  3. PrizeEntry(此表是註冊人數據的來源:EntryID,ListingID,User_ID,Date_Created)

現在所有這些工作都很好,至於將數據存儲在數據庫中。我的問題是SELECT。我有我建立的網站管理員側的自定義模塊,我想執行以下操作:

這裏是我的查詢工作:

SELECT ListingID, Title, ContactEmail, PrizeSponsor 
FROM [BD_Listing] 
WHERE PrizeSponsor = 'True' 

如果我顯示這個數據在網站上的表,它工作正常。問題是,我需要更多的數據,特別是PrizeEntry表中的User_ID。此User_ID需要與Users表中的UserID連接,因爲我需要從其中獲取其他信息。

SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor 
     b.ListingID, b.User_ID 
     FROM BD_Listing a INNER JOIN PrizeEntry b ON a.ListingID = b.ListingID 
     WHERE a.PrizeSponsor = 'True' 

現在,第一個問題出現了。如果有20人註冊必勝客,那麼我會得到21行數據,這不是我要做的。這裏是最終我的代碼加入所有的信息和它的理由,然後你能告訴我怎麼白癡是對做錯了:)

SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor 
     b.ListingID, b.User_ID 
     c.UserID, c.FirstName, c.LastName, c.Email 
     ,(SELECT COUNT(ListingID) AS EntryCount FROM PrizeEntry WHERE (ListingID = a.ListingID)) AS EntryCount 
     ,(SELECT TOP 1 User_ID AS RandomWinner FROM PrizeEntry WHERE (ListingID = a.ListingID)ORDER BY NEWID()) as RandomWinner 

     FROM BD_Listing a INNER JOIN PrizeEntry B on a.ListingID = b.ListingID 
         INNER JOIN Users C on b.User_ID = c.UserID 
     WHERE a.PrizeSponsor = 'True' 

好了,所以在我的表顯示這個數據我只想要必勝客出現一次,但相反,因爲它與PrizeEntry表連接在一起,它會多次出現。

我想看看:

Business: Pizza Hut // comes from the BD_Listing table 
Contact: John Doe // comes from the BD_Listing table 
Total Registrations: 20 // count from the PrizeEntry table 
Random Winner: John Smith (UserID:10) // result from the subquery 

但是,相反,我看到的多行對每個企業,每一個獎項的註冊時間。

我對這段長度表示歉意......我是新來的,這是我的第二篇文章。並閱讀SQL的開始學習曲線。

非常感謝你的任何建議。

+0

你可以包括你當前的數據和所需的輸出?我很難理解你想要做什麼。 – 2012-08-14 21:56:58

+0

我試着回答,但我無法回答。從最終查詢中刪除表「b」和「c」,結果應該是你想要的。要獲得更多信息,請將其作爲子查詢並加入適當的表中。 – 2012-08-14 22:04:19

+0

謝謝大家的幫助。戈登的解決方案對我來說非常合適。但是,我將檢查每一個以更好地理解您的建議。我非常感謝幫助。 – user1447679 2012-08-14 23:44:08

回答

1

首先,如果有20個用戶,你應該想到20行,而不是21

我認爲你可以簡化您的查詢,只需通過移除外連接到用戶,以得到你想要的東西:

SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor, 
     (SELECT COUNT(ListingID) AS EntryCount FROM PrizeEntry pe WHERE (pe.ListingID = a.ListingID)) AS EntryCount, 
     (SELECT TOP 1 User_ID AS RandomWinner FROM PrizeEntry pe WHERE (pe.ListingID = a.ListingID) ORDER BY NEWID()) as RandomWinner 
FROM BD_Listing a 
WHERE a.PrizeSponsor = 'True' 

你想通過贊助商的信息。相關的子查詢獲取附加信息。要獲取有關贏家的詳細信息,只是讓這個子查詢,並加入到相應的表,如下:

with t as (
     SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor, 
       (SELECT COUNT(ListingID) AS EntryCount FROM PrizeEntry pe WHERE (pe.ListingID = a.ListingID)) AS EntryCount, 
       (SELECT TOP 1 User_ID AS RandomWinner FROM PrizeEntry pe WHERE (pe.ListingID = a.ListingID) ORDER BY NEWID()) as RandomWinner 
     FROM BD_Listing a 
     WHERE a.PrizeSponsor = 'True' 
     ) 
select t.*, u.Firstname, u.LastName, u.Email 
from t join 
    users u 
    on t.RandomWinner = u.user_id 
+0

我喜歡這種簡單的方法。我唯一的另一個難題是,需要將PrizeEntry表中的User_ID與Users表中的UserID連接起來,以便我還可以列出隨機獲勝者FirstName,LastName和Email,這些都是用戶表。我感謝您的幫助。你有進一步的建議嗎? – user1447679 2012-08-14 23:26:10

+0

@ user1447679。 。 。這是我最後的建議。我詳細介紹了你的查詢。它只需要在獲得一個獲獎ID後加入信息。 – 2012-08-14 23:32:01

+0

我應該在發佈我的評論之前刷新,我可能會看到它。 :)這是門票!精美的作品。非常感謝你! – user1447679 2012-08-14 23:41:35

0

最簡單的方法是兩個做兩個查詢。第一個獲取贊助商信息,第二個查詢獲取條目。

從技術上講,這是N + 1的情況(請參閱:What is SELECT N+1?),但我不擔心這裏。

理論上你可以一次得到所有東西,然後在前端循環,看看你是否已經打印了贊助商。麻煩的是,那麼做N + 1實際上好多了。

現在,如果您想要關於贊助商的摘要信息不同 - 您可以使用GROUP BY聲明來完成此操作。

像這樣:

SELECT a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor, COUNT(*) AS EntryCount 
    FROM BD_Listing a INNER JOIN PrizeEntry B on a.ListingID = b.ListingID 
        INNER JOIN Users C on b.User_ID = c.UserID 
    WHERE a.PrizeSponsor = 'True' 
    GROUP BY a.ListingID 
0

你會得到,因爲你的加入結構的所有匹配的組合:就當前情況來看你什麼都得不到。

你需要做的是讓參賽者和工作第一齣你的冠軍,那麼這個關聯回到上市:

select a.ListingID, a.Title, a.ContactEmail, a.PrizeSponsor, d.userid, d.firstname, d.lastname, d.email 
from BD_Listing a inner join (
    select top 1 listingid, userid, firstname, lastname, email from (
     select b.ListingID, c.UserID, c.FirstName, c.LastName, c.Email, newid() as ordering 
     from PrizeEntry B INNER JOIN Users C on b.User_ID = c.UserID      
    ) x order by ordering 
) d on a.listingid = d.listingid