Помогите с вложенным запросом! - PullRequest
0 голосов
/ 25 июля 2010
        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!?Большое спасибо ..

Ответы [ 3 ]

2 голосов
/ 25 июля 2010

Сначала попытайтесь избавиться от вставки значений параметров с помощью string.Format в запросы SQL.Это огромная проблема безопасности.

К вашему запросу.Я должен признать, я немного потерян в вашей конкатенации строк :-P, но если я прав, вы хотите получить События и некоторую информацию о пользователе.Насколько я вижу, SenderId и ReciverId уже ваши идентификаторы.Если это так, вы можете полностью удалить первый SELECT и предоставить id (в качестве параметра) непосредственно во второй оператор SQL следующим образом (только SQL):

Редактировать: Том показал мне недостающую часть (Status = Ok)

SELECT TOP (20) a. *, B.UserName в качестве отправителя, c.UserName в качестве получателя, b.Avatar в качестве SenderPic FROM Events a INNER JOIN Usersb ON a.SenderId = b.Id INNER JOIN Пользователи c ON a.ReceiverId = c.Id ГДЕ a.SenderId = @id ИЛИ 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 голос
/ 29 июля 2010
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;
0 голосов
/ 25 июля 2010

Я думаю, что это может помочь:

--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;

Временные таблицы хорошо работают с очень большим объемом данных. В противном случае вы можете использовать таблицу памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...