2012-03-30 3 views
3

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

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

я не имею таблицу со мной, так что его трудно для меня, чтобы сформировать правильный 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 

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

Я никогда не приходилось обновлять таблицу на основании выходного сигнала другого запроса сам до .. Пыталась угадать правильный синтаксис для этого из этого вопроса - How do I UPDATE from a SELECT in SQL Server?

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

+0

спасибо!Начал путаться со временным столом и т. Д., Прежде чем я увидел этот ответ. Пожалуйста, см. Окончательный завершенный запрос ниже для кого-либо еще в симуляционной ситуации. – bigstylee

2

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

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 
Смежные вопросы