我正在ASP.NET中开发一个调查应用程序。我有三个表及其列如下: -
会员(ID,电子邮件,姓名,密码,类型(用户或管理员))
调查(id,ownerId,姓名,surveyHits(填充次数))
问题(id,SurveyId,...其他一些字段)
我将访问调查的每位访客存储在会员表中。
现在我需要的是,我想将调查的所有访问者与调查本身联系起来,这样任何机构都无法进行两次调查。
我该怎么做,或者究竟应该如何保存和跟踪特定调查的访问者?
如果需要,我也可以更改数据库架构......
编辑: -
创建一个存储" surveyId"的组合的新表。和" memberId"作为主键是一个解决方案,但是,
假设我有1,000个调查和10,000个成员。每个成员都填写了每一份调查结果,因此我将仅针对11,000条记录保留 1000万记录。 我能不能提供更有效的解决方案?
答案 0 :(得分:2)
有效率是指节省空间吗?因为EagleRainbow建议的可能是效率最高的。如果您正在寻找节省空间,那么它取决于您可以对成员进行调查的方式进行约束(如果有的话)。
如果有严格的订购,例如会员需要按照id顺序或者created_dtm命令等进行调查,然后你可以在会员上存储他们已完成的最后一次调查。
如果没有订购,那么你可以从EagleRainbow的建议中对表格进行反规范化,但是它需要更多的代码并且需要更长的时间来记录每个调查。您可以存储已完成的连续调查ID(或dtms或其他一些唯一调查标识符)的范围。然后,您可以尽快合并这些记录,并删除冗余记录。
假设您正在录制由其ID完成的调查,那么该表可能如下所示:
<强> CompletedSurveyRange 强>
@range_id
member_id
min_survey_id
max_survey_id
如果成员8765通过调查333开始,则创建记录:
(range_id = 1000,member_id = 8765,min_survey_id = 333,max_survey_id = 333)。
忽略任何其他成员,想象他们接下来会进行调查335.由于已经记录的调查与新调查之间存在差距(334),您需要创建新记录:
(1001,8765,335,335)。
想象一下,下一次完成的调查是332.这可以添加到第一个记录中,因为它是一个相邻的调查。所以你最终得到了这些记录:
(1000,8765,332,333)
(1001,8765,335,335)
我会跳过细节,但想象他们按顺序进行336-340调查,因此记录1001每次都会增加其最大值,最后你得到:
(1000,8765,332,333)
(1001,8765,335,340)
然后他们进行调查334.这填补了记录1000和记录1001之间的空白,因此您可以将它们合并并删除其中一个(实际上并不重要 - 我将随意保留下限ID)。你最终得到:
(1000,8765,332,340)
(1001,8765,335,340)&lt; =删除
如果您有N个调查,那么每个成员最多只有N / 2个实时记录(他们已完成N / 2个调查,其中ID是列表中的每个其他ID)。一旦完成另一个调查,它将下降到(N / 2)-1,因为一个记录将合并到另一个记录中,因此被删除。如果他们以不同于其他模式的模式完成调查,那么进行N / 2次调查将需要少于N / 2次的记录,并且它永远不会超过N / 2.
答案 1 :(得分:1)
我建议引入一个新的数据库表来跟踪成员和调查之间的组合。
CREATE TABLE FilledSurveys (
MemberId as int not null,
SurveyId as int not null,
foreign key (MemberId) references Member(id) on update cascade,
foreign key (SurveyId) references Survey(id) on update cascade,
primary key (MemberId, SurveyId)
);
为确保一致性,您应该使用foreign key关系(请记住,这可能需要使用InnoDB引擎)。这个表也可能使 - 对我来说 - surveyHits
过时的奇怪持久属性Survey
,作为same data can be calculated
飞过
SELECT SurveyId, count(*) as surveyHits
FROM FilledSurveys
GROUP BY SurveyId
但是,请注意:在您的数据库非常匿名且无法跟踪会员/访客的调查结果之前 - 现在这种情况将会消失:调查与会员之间存在明确且持久的关系。