Лучший способ исключить дубликаты без создания новой таблицы

#mysql #sql #subquery

#mysql #sql #подзапрос

Вопрос:

У меня есть запрос, который использует подзапрос, чтобы определить, имеет ли элемент в объединенной таблице повторяющуюся запись, и если это так, данные не извлекаются в родительский запрос:

 select
  (f.listing_datetime) as datetime,
  round(avg(f.listing_price), 0) as price,
  round(avg(f.listing_sqft), 0) as sqft,
  round(avg(f.listing_p_per_sqft), 2) as p_per_ft,
  f.listing_neighborhood, count(*) as points
from ( 
    select
      a.listing_datetime, a.listing_price, a.listing_sqft, a.listing_p_per_sqft,
      a.listing_neighborhood, i.listing_tokens, count(i.listing_tokens) as c
    from
      agg_cl_data as a
      left join incoming_cl_data_desc as i
        on a.listing_url = i.listing_url
    where a.listing_datetime between curdate() - interval 30 day and curdate()
    group by i.listing_tokens
    having c < 2
  ) as f
group by day(f.listing_datetime), f.listing_neighborhood
order by f.listing_datetime;
  

Как вы можете видеть, используя простой способ борьбы с дубликатами с помощью предложения HAVING, я фактически теряю исходную запись, которая была сохранена, потому что любая агрегированная запись с большим, чем 2, выбрасывается. Есть ли лучший способ сделать это, чтобы я не потерял часть данных, НЕ создавая новую таблицу, к которой будут запрашиваться запросы?

Комментарии:

1. Ваш текущий подзапрос недействителен, потому что вы группируете по listing_tokens одному, но затем переходите к выбору многих других столбцов.

2. выполняется текущий запрос, и предполагается группировать только по токенам в подзапросе. Возможно, я неправильно понимаю ваш комментарий

3. В агрегированном запросе SQL разрешает выбирать только столбцы группировки, если таковые имеются, и (агрегированные) функции групп. Вы выбираете много других столбцов, как в подзапросе, так и в основном запросе. MySQL допускает это как расширение, но результаты зависят от порядка, в котором извлекаются строки каждой группы.

4. Удалить having предложение? Образцы данных и желаемые результаты действительно помогли бы.

5. Когда есть несколько одинаковых результатов i.listing_tokens , какой из них вы хотите, чтобы запрос вернул?

Ответ №1:

Если вы хотите удалить повторяющиеся строки, используйте предложение DISTINCT . Если вы хотите найти дубликат на основе разбиения на определенный столбец, используйте функцию окна ROW_NUMBER .

На первый взгляд, ваш подзапрос недействителен, поскольку вы группируете по одному столбцу и не используете какую-либо другую агрегатную функцию в других столбцах.

 select distinct
  a.listing_datetime, a.listing_price, a.listing_sqft, a.listing_p_per_sqft,
  a.listing_neighborhood, i.listing_tokens
from
  agg_cl_data as a
  left join incoming_cl_data_desc as i
    on a.listing_url = i.listing_url
where a.listing_datetime between curdate() - interval 30 day and curdate()
  

Комментарии:

1. Проблема в том, что ни один из этих столбцов не уникален, но я хочу определить дубликат по столбцу listing_tokens , поэтому distinct не будет работать, потому что distinct будет сравниваться по всем этим столбцам, и вы можете определить дубликат только из столбца listing_tokens

2. кроме того, не сработает ли этот подзапрос, потому что если c < 2, то нет никакой двусмысленности в отношении других значений столбцов. если c> 1, то это неоднозначно, но эти значения все равно не выбираются из-за предложения having ?

Ответ №2:

Попробуйте использовать ‘distinct’ вместо, если ‘having’ в подзапросе. Вы получите каждый URL-адрес только один раз, не теряя его, даже если для него было две записи.

Итак, ваш код должен быть:

 select DISTINCT a.listing_datetime, ...
  

и тогда в конце нет «наличия».