我有下表
| Path | Version | FirstName | LastName |
| People/Frank | 1 | Frank | Smith |
| People/Frank | 2 | Frank | Jones |
| People/Jack | 1 | Jack | Johnson |
我希望我的查询为所有符合给定条件的行返回Path
和Max Version
。
目前我正在这样做;
select Path, MAX(Version) as Version from Table where FirstName = 'Frank' group by Path;
这是代码中一个非常重要的性能部分,我想知道我是否可以对sql server做些具体的事情,这会使这个更快或者是否有我遗漏的东西。
此外,我想确保正确定义约束。我希望查询包含任何或所有不是路径和版本的列,因此您可以在上面的情况下查询FirstName,LastName或两者。我的create table sql看起来像这样:
create table Index_PersonByFirstName(
FirstName NVarChar(100) not null,
LastName NVarChar(100) not null,
Path NVarChar(100) not null,
Version Int not null,
constraint pk_Index_PersonByFirstName primary key(
FirstName,
LastName,
Path,
Version),
constraint uc_Index_PersonByFirstName_Path_Version unique (
Path,
Version),
constraint fk_People_Path_Version foreign key (
Path,
Version) REFERENCES People(Path, Version))
从主键中删除Path
是否有意义,因为它永远不会被直接查询?
我考虑的另一个选项是有一个列,指示该行是否是给定路径的“最新”版本,并在写入新行时更新旧行,但感觉很糟糕。
您的想法将不胜感激。如果我还不够详细,请告诉我,我将添加所需的任何其他信息。
答案 0 :(得分:1)
查询没问题。这是教科书正确的方法。
主键应该是唯一标识记录的最小字段集。您的示例是在您的实际数据库之上还是仅仅是一个简化或假设的示例?因为名字和姓氏不太可能保证是唯一的。你确定你永远不会有两个“吉姆史密斯”吗?我不知道如何定义“路径”。也许这是在你的控制之下,所以你可以保证它是独一无二的。
请勿将字段添加到主键,因为这是您要排序或选择的内容。使用备用索引。
根据您对示例的猜测进行更新
我不知道您的数据意味着什么或您想要做什么。但我猜第一个和最后一个名字真的依赖于路径。也就是说,你不会:
path vers first name last name
---- ---- ---------- ---------
/foo/fredm 1 Fred Miller
/foo/fredm 2 Fred Miller
/foo/fredm 1 Sally Jones
如果这是真的,那么你真的应该有一个包含Path,First Name,Last Name,可能是其他数据和Path的键的表。然后是一个单独的表,其中包含Path和Version以及任何数据,这取决于版本。
否则,您的数据库可能包含相互矛盾的数据。如果一个Path应该只映射到一个名称,如果通过某种编码或数据输入错误,你得到一条带有“fredm”路径并命名为“Fred Miller”而另一条带有路径“fredm”和名称的记录会发生什么“弗兰克孟德尔”?期望它们总是相同的查询可能最终随机选择一个并给出不一致的结果,或者你可以得到两个你认为应该有一个的记录,等等。好的数据库设计的一个主要规则是:不要存储冗余数据。