2016-10-07 1 views
2
.

. Раньше я извлекал некоторые данные и обнаружил, что мои результаты слишком многочисленны для использования (более 4 миллионов строк возвращены). Я обнаружил, что виновником является большое количество идентификаторов, которые имеют несколько тысяч записей за штуку.Исключить строки из SQL-запроса на основе количества строк. ID присутствует в

Heres Структура данных. У меня две таблицы. tbl1 имеет единственную запись каждого «ATID» (ATID - это идентификатор масштаба, в основном). Тем не менее, каждый ATID является, по сути, своей собственной таблицей - он имеет запись для каждого элемента шкалы. tbl2 перечисляет эти элементы - у него есть строка для каждого элемента шкалы для ATID. Таким образом, он имеет от 1 до 500 000 строк для каждого ATID (я знаю, довольно сильно из-за чрезмерного).

Я хотел бы исключить ATID, у которых более 100 строк. FYI это база данных, к которой я имею доступ только для чтения.

Вот мой исходный запрос:

SELECT tbl1.ATID, tbl1.ATDesc, tbl2.AValue, tbl2.ADesc, tbl2.APosNeg 
FROM tbl1 LEFT OUTER JOIN tbl2 ON (tb1.ATID = tbl2.ATID); 

Вот запрос я использовал, чтобы получить список ATIDs и записи отсчетов в tbl2 на ATID:

select ATID, count(*) as row_count 
from tbl2 
group by ATID 
order by row_count desc; 

Для моего конечного продукта, который я хотел бы для возврата только ATID с менее чем 100 строк в tbl2. Однако, если я даже попытаюсь добавить предложение WHERE ко второму запросу, используя переменную row_count, он терпит неудачу. Поэтому я не знаю, как подойти к объединению двух запросов и получить предложение WHERE.

Единственная альтернатива, которую я имею, заключается в том, чтобы исключить ATID специально, когда я знаю, что у них слишком много записей, но их слишком много, чтобы исключить (то есть, с помощью WHERE NOT ATID = 1016 AND NOT ATID = 554 AND NOT .... и т.д.)

+0

Вы знаете, как выполнить подзапрос? –

ответ

3

вы уже сделали это, вам просто нужно положить два запроса вместе:

SELECT tbl1.ATID, tbl1.ATDesc, tbl2.AValue, tbl2.ADesc, tbl2.APosNeg 
FROM tbl1 LEFT OUTER JOIN tbl2 ON (tb1.ATID = tbl2.ATID) 
WHERE tbl1.ATID NOT IN (
    select ATID 
    from tbl2 
    group by ATID 
    HAVING COUNT(*) >= 100 
) 
3

Вот один из способов сделать это, используя

Count() Over() оконный агрегат будет count количество записей для каждого ATID в tbl2 стол. Затем посчитать можно использовать для фильтрации ATID в Join условию

SELECT tbl1.ATID, 
     tbl1.ATDesc, 
     tbl2.AValue, 
     tbl2.ADesc, 
     tbl2.APosNeg 
FROM tbl1 
     LEFT OUTER JOIN (SELECT Count(1)OVER(partition BY ATID) AS cnt,* 
         FROM tbl2) tbl2 
        ON tb1.ATID = tbl2.ATID 
         AND tbl2.cnt <= 100; 

Примечание: Если вы не хотите все ATID's из tabl1 затем перейти условие tbl2.cnt <= 100 к Where пункта, так что вы получите счетчик ATID's которого счетчик меньше 100 в tbl2

1

Для SQL-сервера используйте CTE (быстрее, чем запрос). Кроме того, ненужные скобки в запросе

with RowCo as 
(
select ATID, count(*) as row_count 
from tbl2 
group by ATID 
having row_count <= 100 
) 

SELECT tbl1.ATID, tbl1.ATDesc, tbl2.AValue, tbl2.ADesc, tbl2.APosNeg 
FROM tbl1 
inner join RowCo 
    on RowCo.ATID = tbl1.ATID 
LEFT JOIN tbl2 
    ON tb1.ATID = tbl2.ATID 
+0

Спасибо - что делает CTE быстрее, чем подзапрос? – user2784067

1

Для второго запроса, фильтры, связанные с агрегатными функциями идет на HAVING секции

select ATID, count(*) as row_count 
from tbl2 
group by ATID 
order by row_count desc; 
having count(*) < 100 

И для первого запроса вы можете просто использовать подзапрос

SELECT tbl1.ATID, tbl1.ATDesc, tbl2.AValue, tbl2.ADesc, tbl2.APosNeg 
FROM tbl1 
    LEFT OUTER JOIN tbl2 ON (tb1.ATID = tbl2.ATID) 
WHERE tbl1.ATID in (select ATID 
        from tbl2 
        group by ATID 
        having count(*) < 100)