Запрос SQL Server: ВЫБЕРИТЕ 1, ГДЕ СУЩЕСТВУЕТ, а ВЫБЕРИТЕ ТОП 1 1 - PullRequest
3 голосов
/ 19 января 2010

Мне нужно представить флаг - 0, если условие не выполняется, 1, если оно есть, и я могу сделать это двумя различными способами:

Получить идентификатор сотрудника, имя, 1, если есть другие в подзаказе - 0, если нет:

SELECT e.ID
     , e.Name
     , ISNULL ( ( SELECT TOP 1 1 FROM Employee se WHERE se.ManagerID = e.ID ) , 0 ) AS HasSubordinates 
  FROM Employee e

или

SELECT e.ID
     , e.Name
     , ISNULL ( ( SELECT 1 WHERE EXISTS ( SELECT * FROM Employee se WHERE se.ManagerID = e.ID ) ) , 0 ) AS HasSubordinates 
  FROM Employee e

Какую версию вы бы выбрали и почему?


Обновление 1


Как насчет этого?

SELECT o.ID
     , o.Name
     , o.StartDate
     , o.EndDate
     , ISNULL ( ( SELECT TOP 1 1 FROM changes c WHERE c.ChangeDate BETWEEN o.StartDate AND o.EndDate ) , 0 ) AS IsChanged
  FROM Orders o

или

SELECT o.ID
     , o.Name
     , o.StartDate
     , o.EndDate
     , ISNULL ( ( SELECT 1 WHERE EXISTS ( SELECT * FROM changes c WHERE c.ChangeDate BETWEEN o.StartDate AND o.EndDate ) ), 0 ) AS IsChanged
  FROM Orders o

Ответы [ 2 ]

8 голосов
/ 19 января 2010

Ни один, я бы использовал:

   SELECT t.id,
          t.name,
          CASE WHEN x.managerid IS NULL THEN 0 ELSE 1 END AS HasSubordinates 
     FROM EMPLOYEE t
LEFT JOIN (SELECT DISTINCT 
                  e.managerid
             FROM EMPLOYEE e) x ON x.managerid = t.id

... потому что коррелированные SELECTS в предложении SELECT плохие - они не масштабируются, потому что они выполняются для каждой возвращаемой строки. Это означает, что чем больше строк, тем больше будет вызываться коррелированный SELECT.

2 голосов
/ 19 января 2010

Я бы тоже не стал ...

Причина в том, что (и это насколько я знаю), когда у вас есть подвыбор в операторе select, этот отбор будет выполняться один раз для каждой возвращаемой строки. Следовательно, если бы у вас было 100 строк, возвращаемых основным запросом, вы бы фактически выполнили 101 запрос. Когда вы используете объединение, вы делаете только один запрос, который должен совпасть слева и справа. Обратите внимание, что это поможет, если у вас есть индекс на ManagerId.

Попробуйте что-то вроде этого:

SELECT e.ID,
       e.Name,
       COUNT(se.ID) AS TotalStaff
FROM    Employee e 
        LEFT JOIN Employee se 
                ON se.ManagerID = e.ID
GROUP BY e.ID, e.Name 

Это немного отличается от того, что было у вас, так как я возвращаю сумму, а не просто 0 | 1, но это легко изменить, если вам нужно 1 | 0 ...

Дайте мне знать, если это поможет

...