我有一个调查表,其中包含(除其他外)以下列
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的目的是显示在12个月内(创建日期的+/-6个月)收到的相同user_id的重复ip_address调查提交的数量。
使用以下数据集,这是预期的结果。
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
感谢您提前提供的帮助:)
对上面显示的内容进行了一些(非常)小的调整。再次感谢!
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
我没有你的表,所以我很难形成正确的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)
该输出应包含匹配(根据您的规则)两次的每对调查(每个id在第一位置一次,在第二位置一次)
然后,我们可以对其输出进行GROUP BY
,以获得一个表,该表基本上为每个survey_id 提供了正确的ip_count
(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
里面有一些伪代码,但我认为总的想法应该适用于
我以前从未根据另一个查询的输出更新过表。。试着从这个问题中猜测正确的语法——如何在SQL Server中从SELECT进行更新?
此外,如果我需要为自己的工作做这样的事情,我不会试图在一个查询中完成。。这将是一个很难维护的问题,并且可能存在内存/性能问题。最好是让脚本逐行遍历表,在转到下一行之前更新事务中的一行。速度慢得多,但理解起来更简单,而且数据库可能更轻。