2010-10-13 3 views
1

Ниже приведен пример запроса того, что я пытаюсь сделать, и он выполняет эту работу, но я чувствую, что sub-запросы - это не лучший способ пойти сюда. Любые указатели?Могу ли я оптимизировать этот запрос sql?

SELECT DISTINCT 
    u.UserID, 
    (SELECT COUNT(LoginID) FROM Logins WHERE Success = 1 AND UserID = u.UserID) AS Successful, 
    (SELECT COUNT(LoginID) FROM Logins WHERE Success = 0 AND UserID = u.UserID) AS Unsuccessful,   
    (SELECT TOP 1 LoginDate FROM Logins WHERE UserID = u.UserID ORDER BY LoginDate DESC) AS LastLogin 
FROM 
    Users u INNER JOIN 
    Logins l ON u.UserID = l.UserID 

BTW приведенный выше пример не выглядит, как он нуждается присоединиться, но в реальном решении сделать, чтобы получить некоторые другие столбцы ...

+0

Можете ли вы опубликовать план выполнения? –

+0

Мне кажется, что вы можете делать все запросы из логинов в одном элементе вместо трех, используя что-то вроде 'sum (if success = 0 then 1 else 0 endif)'? –

ответ

6

Я пропускаю что-то значительное, или вы не могли бы сделать это с одним агрегированным запросом?

SELECT u.UserID, 
    SUM(CASE WHEN Success = 1 THEN 1 ELSE 0 END) AS Successful, 
    SUM(CASE WHEN Success = 0 THEN 1 ELSE 0 END) AS Unsuccessful, 
    MAX(LoginDate) AS LastLogin 
FROM Users u 
INNER JOIN Logins l on u.UserID = l.UserID 
GROUP BY u.UserID 
+0

+1: Ты избил меня –

+0

Да, это то, что я имел в виду под моим комментарием. Я не ответил на этот вопрос, потому что не был уверен в синтаксисе. Хорошо, потому что я ошибся. –

+0

Мне любопытно посмотреть, как это работает по сравнению с моим примером. – ChaosPandion

0

Вы можете попробовать, если это более эффективно в вашей ситуации:

select 
    u.UserID, 
    sum(case when l.Success = 1 then 1 else 0 end) as Successful, 
    sum(case when l.Success = 0 then 1 else 0 end) as Unsuccessful, 
    max(LoginDate) as LastLogin 
from 
    Users u 
    inner join Logins l on l.UserID = u.UserID 
group by 
    u.UserId 
1

Я хотел бы попробовать что-то вроде этого:

declare @Users Table (UserID int) 
declare @Logins Table (LoginID int, UserID int, LoginDate DateTime, Success Bit) 

Insert into @Users 
select 1 union select 2 

insert into @Logins 
select 1, 1, '2010-10-13 6:00:00', 1 
union 
select 2, 1, '2010-10-13 7:00:00', 0 
union 
select 3, 1, '2010-10-13 8:00:00', 1 
union 
select 4, 2, '2010-10-13 6:00:00', 0 
union 
select 5, 2, '2010-10-13 7:00:00', 1 
union 
select 6, 2, '2010-10-13 9:00:00', 1 
union 
select 7, 2, '2010-10-13 10:00:00', 1 

Select UserID, 
      [1] As Successful, 
      [0] As Unsuccessful, 
      LoginDate As LoginDate 
From (
    SELECT 
     u.UserID, 
     l.LoginID, 
     l.Success, 
     Max(LoginDate) Over (Partition By u.UserID) As LoginDate 
    FROM @Users u 
     INNER JOIN @Logins l ON u.UserID = l.UserID 
) Data Pivot (
    Count(LoginID) For Success In (
     [0], [1] 
    ) 
) Result 
Смежные вопросы