Обновление mysql с помощью самообращающегося запроса - PullRequest
4 голосов
/ 30 марта 2012

У меня есть таблица опросов, которая содержит (среди прочего) следующие столбцы

survey_id  - unique id
user_id    - the id of the person the survey relates to
created    - datetime
ip_address - of the submission
ip_count   - the number of duplicates

Из-за большого набора записей нецелесообразно запускать этот запрос на лету, поэтому пытаюсь создать обновлениеоператор, который будет периодически хранить «кэшированный» результат в ip_count.

Цель ip_count - показать количество дубликатов, полученных для опроса ip_address, для того же user_id с 12-месячным периодом (+/- 6 месяцев от даты создания).

Используя следующий набор данных, это ожидаемый результат.

survey_id   user_id    created    ip_address     ip_count  #counted duplicates survey_id
  1            1      01-Jan-12   123.132.123       1      # 2
  2            1      01-Apr-12   123.132.123       2      # 1, 3
  3            2      01-Jul-12   123.132.123       0      # 
  4            1      01-Aug-12   123.132.123       3      # 2, 6
  6            1      01-Dec-12   123.132.123       1      # 4

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

UPDATE surveys
JOIN(
  SELECT ip_address, created, user_id, COUNT(*) AS total
  FROM surveys  
  WHERE surveys.state IN (1, 3) # survey is marked as completed and confirmed
  GROUP BY ip_address, user_id
) AS ipCount 
  ON (
    ipCount.ip_address = surveys.ip_address
    AND ipCount.user_id = surveys.user_id
    AND ipCount.created BETWEEN (surveys.created - INTERVAL 6 MONTH) AND (surveys.created + INTERVAL 6 MONTH)
  )
SET surveys.ip_count = ipCount.total - 1 # minus 1 as this query will match on its own id.
WHERE surveys.ip_address IS NOT NULL # ignore surveys where we have no ip_address

Спасибо за вашу помощь заранее:)

Ответы [ 2 ]

3 голосов
/ 30 марта 2012

Несколько (очень) незначительных твиков к тому, что показано выше.Еще раз спасибо!

UPDATE surveys AS s
INNER JOIN (
  SELECT x, count(*) c
  FROM (
    SELECT s1.id AS x, s2.id AS y
    FROM surveys AS s1, surveys AS s2
    WHERE s1.state IN (1, 3) # completed and verified
      AND s1.id != s2.id # dont self join
      AND s1.ip_address != "" AND s1.ip_address IS NOT NULL # not interested in blank entries
      AND s1.ip_address = s2.ip_address
      AND (s2.created BETWEEN (s1.created - INTERVAL 6 MONTH) AND (s1.created + INTERVAL 6 MONTH))
      AND s1.user_id = s2.user_id # where completed for the same user
  ) AS ipCount
  GROUP BY x
) n on s.id = n.x
SET s.ip_count = n.c
2 голосов
/ 30 марта 2012

У меня нет твоего стола, поэтому мне сложно сформировать правильный sql, который определенно работает, но я могу попробовать и надеяться, что смогу тебе помочь.

Сначала мне нужно взять декартово произведение опросов против себя и отфильтровать строки, которые мне не нужны

select s1.survey_id x, s2.survey_id y from surveys s1, surveys s2 where s1.survey_id != s2.survey_id and s1.ip_address = s2.ip_address and (s1.created and s2.created fall 6 months within each other)

Вывод этого должен содержать каждую пару опросов, которые соответствуют (согласно вашим правилам) ДВАЖДЫ (один раз для каждого идентификатора в 1-й позиции и один раз для того, чтобы он был во 2-й позиции)

Затем мы можем сделать GROUP BY на выходе этого, чтобы получить таблицу, которая в основном дает мне правильный ip_count для каждого survey_id

(select x, count(*) c from (select s1.survey_id x, s2.survey_id y from surveys s1, surveys s2 where s1.survey_id != s2.survey_id and s1.ip_address = s2.ip_address and (s1.created and s2.created fall 6 months within each other)) group by x)

Итак, теперь у нас есть таблица, отображающая каждый survey_id на его правильный ip_count. Чтобы обновить исходную таблицу, нам нужно объединить ее с этим и скопировать значения в

Так что это должно выглядеть примерно так:

UPDATE surveys SET s.ip_count = n.c from surveys s inner join (ABOVE QUERY) n on s.survey_id = n.x

Там есть некоторый псевдокод, но я думаю, что общая идея должна работать

Раньше мне никогда не приходилось обновлять таблицу на основе результатов другого запроса. Попытка угадать правильный синтаксис для этого из этого вопроса - Как ОБНОВИТЬ из SELECT в SQL Server?

Также, если бы мне нужно было сделать что-то подобное для моей собственной работы, я бы не стал пытаться сделать это в одном запросе. Это было бы трудно поддерживать и могло бы иметь проблемы с памятью / производительностью. Лучше всего, чтобы скрипт проходил по таблице строку за строкой, обновлял одну строку в транзакции перед тем, как перейти к следующей строке. Намного медленнее, но проще для понимания и, возможно, легче в вашей базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...