2015-12-04 2 views
1

предположить, что я имею следующую activity таблицы:SQL запрос, чтобы выбрать строки, которые основаны на некотором значении других строк в одной таблице

id  type value flag 
------|------|-------|------| 
1  |A  | 13 | 1 | 
2  |B  | 29 |  | 
3  |C  | 11 |  | 
4  |A  | 78 |  | 
5  |X  | 91 |  | 
6  |C  | 2  |  | 
7  |B  | 14 | 1 | 

Я хочу, чтобы выбрать строки, любая строка с тем же типом имеет флаг 1 или тип X. В этом случае, я хотел бы получить:

id  type value flag 
------|------|-------|------| 
1  |A  | 13 | 1 | 
4  |A  | 78 |  | 
2  |B  | 29 |  | 
7  |B  | 14 | 1 | 
5  |X  | 91 |  | 

я могу сделать INNER JOIN, чтобы получить результат, как:

SELECT 
    "activities".* 
FROM "activities" 
INNER JOIN activities AS a2 
    ON activities.type = a2.type 
    AND a2.flag = 1 
    OR activities.type = 'X' 
    AND activities.id = a2.id 

Однако, это происходит медленно, когда количество записей становится большим, особенно когда Мне нужно сделать COUNT(*) поверх результата. Интересно, как я могу переписать запрос и сделать его более результативным.

Я использую Postgres. Благодаря!

ответ

1

Вот 3 способа сделать это. Выберите тот, который будет работать быстрее в вашем наборе данных. Чтобы ускорить эти запросы, вам необходимо создать индексы на type и flag.

select a.* from activities a 
JOIN (select distinct type FROM activities where type='X' or flag=1) t 
ON a.type=t.type; 


select a.* from activities a 
where type='X' 
    or EXISTS(SELECT * FROM activities WHERE type=a.type AND flag=1); 


select a.* from activities a 
where type='X' 
    or type IN (SELECT type FROM activities WHERE flag=1) 

SQLFiddle demo

1

Попробуйте это решение

SELECT id, 
     type, 
     value, 
     flag 
FROM (SELECT *, 
     SUM(CASE WHEN flag = 1 THEN 1 ELSE 0 END) OVER (PARTITION BY type) AS flag_occurence_for_type 
     FROM activities) t 
WHERE type = 'X' OR flag_occurence_for_type > 0 
Смежные вопросы