SQL объединить два подзапроса - PullRequest
0 голосов
/ 12 июня 2010

У меня есть две таблицы.Таблица A имеет столбец id.Таблица B имеет столбец Aid и столбец type.Пример данных:

A:  id
    --
    1
    2

B: Aid | type
   ----+-----
   1   |  1
   1   |  1
   1   |  3
   1   |  1
   1   |  4
   1   |  5
   1   |  4
   2   |  2
   2   |  4
   2   |  3

Я хочу получить все идентификаторы из таблицы A, в которой есть определенное количество действий типа 1 и типа 3.Мой запрос выглядит так:

SELECT id 
FROM A
WHERE (SELECT COUNT(type)
       FROM B
       WHERE B.Aid = A.id
         AND B.type = 1) = 3 
  AND (SELECT COUNT(type)
       FROM B
       WHERE B.Aid = A.id
         AND B.type = 3) = 1

, поэтому по приведенным выше данным должен быть возвращен только идентификатор 1.

Можно ли как-то объединить 2 подзапроса?Цель - ускорить выполнение запроса.

Ответы [ 4 ]

1 голос
/ 12 июня 2010
Select ...
From A
    Join    (
            Select B.Id
                , Sum ( Case When B.Type = 1 Then 1 Else 0 End ) As Type1Count
                , Sum ( Case When B.Type = 3 Then 1 Else 0 End ) As Type3Count
            From B
            Where B.Type In(1,3)
            Group By B.Id
            ) As Z
        On Z.Id = A.Id
Where Z.Type1Count = 3
    And Z.Type3Count = 1
1 голос
/ 12 июня 2010

Поддерживает ли postgres CTE?

WITH counts (Counts, Type, Aid) as (
  select count(type), type
  from b group by Type, Aid
)
  select id
  from A
  join Counts B1 on b1.Aid = a.id and b1.type = 1
  join Counts B3 on b3.Aid = a.id and b3.type = 3
where
  b1.counts = 3 and b3.counts = 1

Я бы предложил сравнить планы выполнения, но я подозреваю, что это будет похоже, поскольку все должно быть свернуто до выполнения.

0 голосов
/ 12 июня 2010

Другая альтернатива:

SELECT DISTINCT Aid FROM (
   SELECT Aid,type,count(*) as n from B 
   GROUP BY Aid,type, ) as g 
 WHERE ( g.n=1 AND  g.type =  3 ) 
   OR  ( g.n=3 AND  g.type =  1 ) 

Я сомневаюсь, что это будет работать лучше, чем ваш оригинал.Вы, кажется, делаете лучшую стратегию: считайте только строки-кандидаты.Возможно, поможет некоторая избыточная предварительная фильтрация:

SELECT DISTINCT Aid FROM (
   SELECT Aid,type,count(*) as n from B
   WHERE g.type =  3 OR g.type =  1  -- prefilter 
   GROUP BY Aid,type, ) as g 
 WHERE ( g.n=1 AND  g.type =  3 ) 
   OR  ( g.n=3 AND  g.type =  1 ) 
0 голосов
/ 12 июня 2010

Это работает в TSQL, это работает в Postgres?

SELECT A.ID
FROM A
WHERE A.ID in
(
SELECT AID
FROM B
GROUP BY AID
HAVING
  SUM(CASE WHEN Type = 1 THEN 1 ELSE 0 END) = 3
  OR SUM(CASE WHEN Type = 3 THEN 1 ELSE 0 END) = 1
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...