2010-07-25 74 views
0
 int id = 1; 
     string chain = "("; 
     SqlDataReader dr = SqlHelper.ExecuteReader(string.Format("SELECT a.Id as x, c.Id as y From Friends b INNER JOIN Users a ON b.SenderId = a.Id INNER JOIN Users c ON b.ReceiverId = c.Id WHERE (c.Id = {0} OR a.Id = {0}) AND State = '{1}'", id, "ok")); 
     if (dr.HasRows) 
      while (dr.Read()) 
       if (id == int.Parse(dr["y"].ToString())) 
        chain += dr["x"].ToString() + ", "; 
       else 
        chain += dr["y"].ToString() + ", "; 
     if (chain.Length > 1) 
      chain = chain.Substring(0, chain.Length - 2) + ")"; 
     else 
      chain = "(0)"; 
     // Chain has for example => (2, 3, 4, 5) => which are the Ids for Users's Friends 
     string str = "SELECT TOP 20 a.*, b.UserName as Sender, c.UserName as Receiver, b.Avatar as SenderPic"; 
     str += " FROM Events a INNER JOIN Users b ON a.SenderId = b.Id INNER JOIN Users c ON a.ReceiverId = c.Id "; 
     str += "WHERE SenderId IN "; 
     str += chain; 
     str += " OR ReceiverId IN"; 
     str += chain; 
     str += " Order BY Id desc"; 
     dr = SqlHelper.ExecuteReader(str); 

chain認爲是用戶的朋友。 有沒有人知道如何用JOINS執行這個查詢!?非常感謝。幫助嵌套查詢!

+1

我認爲你應該刪除C#代碼,並將涉及的SQL的問題重新說明。包含一些關於模式的更多信息。這可能會給你更多的答案。 – driis 2010-07-25 08:51:33

+0

很難弄清楚你真正感興趣的東西。發佈的代碼樣本非常混亂,很難理解。如果您想知道如何將帶有WHERE SenderId IN(....)的SQL查詢轉換爲帶JOIN的查詢,那麼請給我們看看這個SQL查詢 - 而不是生成它的C#代碼... ....你讓它不必要的困難和困難讓人們回答你..... – 2010-07-25 08:53:45

+0

第一個查詢中匹配的「ReceiverId」是否應該符合第二個匹配「SenderId」的條件? – 2010-07-25 09:07:58

回答

1
SELECT distinct TOP(20) e.*, u1.UserName As Sender, 
u2.UserName As Receiver, u1.Avatar AS SenderPic 
FROM Friends f INNER JOIN Users u 
ON(u.Id = f.SenderId OR u.Id = f.ReceiverId) AND State = 'ok' 
INNER JOIN Events e 
ON(f.SenderId = e.SenderId OR f.SenderId = e.ReceiverId 
OR f.ReceiverId = e.SenderId OR f.ReceiverId = e.ReceiverId) 
INNER JOIN Users u1 
ON (e.SenderId = u1.Id) 
INNER JOIN Users u2 
ON (e.ReceiverId = u2.Id) 
WHERE u.Id = @id; 
2

首先,嘗試擺脫使用string.Format將參數值推入SQL查詢。這是一個巨大的安全問題。

查詢。我不得不承認,在字符串連接中我有點失落:-P,但是如果我是對的,你想獲得事件和一些用戶信息。據我所知,SenderId和ReciverId已經是你的ID了。如果是這樣,你可以完全去除第一選擇,並提供ID(如參數),直接到你這樣的第二個SQL語句(僅SQL):

編輯:湯姆向我展示了缺失的部分(狀態= OK)

SELECT TOP(20) 一個。* ,b.UserName如發件人 ,c.UserName作爲接收機 ,b.Avatar如SenderPic FROM活動一個 INNER JOIN用戶b關於a.SenderId = b.Id INNER JOIN用戶c ON a.Receive rId = c.Id WHERE a.SenderId = @id OR a.ReceiverId = @id;


修正版本:

; WITH OkUsers AS (
    SELECT 
     u.* 
    FROM Users u 
     JOIN Friends f ON u.Id = f.SenderId OR u.Id = f.RecipientId 
    WHERE 
     f.Status = 'Ok' 
) 
SELECT TOP(20) 
    a.* 
    ,b.UserName as Sender 
    ,c.UserName as Receiver 
    ,b.Avatar as SenderPic 
FROM Events a 
    INNER JOIN OkUsers b ON a.SenderId = b.Id 
    INNER JOIN OkUsers c ON a.ReceiverId = c.Id 
WHERE 
    a.SenderId = @id 
    OR a.ReceiverId = @id; 
+1

絕對+1 - 將SQL命令連接在一起就是一個巨大的GAPING SQL注入漏洞,等待被利用! – 2010-07-25 08:54:38

+0

我認爲原文在Friends.State ='ok'上有一個額外的WHERE子句(假設狀態列在朋友表上定義) – 2010-07-25 09:06:16

+0

@Tom Carver感謝提示。我更新了SQL語句。 – 2010-07-25 09:16:06

0

我認爲這可能幫助:

--step[1] 
SELECT DISTINCT CASE 
WHEN a.Id = 1 THEN c.ID 
WHEN c.Id = 1 THEN a.Id 
ELSE 
0 
END AS ID 
INTO #OkUsers 
From Friends b INNER JOIN Users a 
ON b.SenderId = a.Id INNER JOIN Users c 
ON b.ReceiverId = c.Id 
WHERE (c.Id = @id OR a.Id = @id) AND State = 'Ok'; 

--step[2] 
SELECT TOP 20 a.*, b.UserName as Sender, c.UserName as Receiver, b.Avatar as SenderPic 
FROM Events a INNER JOIN Users b ON a.SenderId = b.Id INNER JOIN Users c ON a.ReceiverId = c.Id 
INNER JOIN #OkUsers ON #OkUsers.ID = SenderId OR #OkUsers.ID = ReceiverId 
EXCEPT 
SELECT TOP 20 a.*, b.UserName as Sender, c.UserName as Receiver, b.Avatar as SenderPic 
FROM Events a INNER JOIN Users b ON a.SenderId = b.Id INNER JOIN Users c ON a.ReceiverId = c.Id 
--INNER JOIN #OkUsers ON #OkUsers.ID = SenderId OR #OkUsers.ID = ReceiverId 
WHERE SenderId IN (SELECT ID FROM #OkUsers) 
    OR ReceiverId IN(SELECT ID FROM #OkUsers); 

DROP TABLE #OkUsers; 

臨時表工作良好,體積非常大data.Otherwise,你可以使用一個內存表。

+0

我該如何在我的代碼中使用它! 此外,我已經提取所有的識別號碼給一個成員的所有朋友,然後把它放在一個String類型的變量中,用於第二個查詢中的IN子句。是一個好方法還是什麼! – Rawhi 2010-07-25 10:06:37

+0

任何SQL代碼只會在一次行程中給出最終結果,而不是在兩次往返中執行。從sql server獲取數據到內存中並使用它的性能要比使用sql server做更好,但這不是一個總是有效的規則,因爲它取決於數據量,應用程序服務器容量和用戶負載...等 – 2010-07-25 10:28:03

+0

我什至不能想到這可以寫在一個單一的SQL語句! #OkUsers => SELECT => DROP – Rawhi 2010-07-25 11:58:20