3

我的数据库中有以下表格,我无法更改或修改。我使Log表格保持简单,但LogDetail与我的数据库中的相同。

日志表

 Id  User Department Service     Method

 21  John Sales      UserService GetUser

日志明细表

Id LogRef ParamName  ParamValue

30 21     FirstName  Adam
31 21     LastName   Smith     
32 21     Age        35
33 21     Gender     M

现在,我正在使用以下查询来获取搜索者(Adam,Smith,35,M)

SELECT 
L.*, D1.ParamName, D2.ParamName, D3.ParamName, D4.ParamName
FROM Log as L
INNER JOIN LogDetail as D1 on L.Id = D1.LogRef
INNER JOIN LogDetail as D2 on L.Id = D2.LogRef
INNER JOIN LogDetail as D3 on L.Id = D3.LogRef
INNER JOIN LogDetail as D4 on L.Id = D4.LogRef
WHERE
D1.ParamName='FirstName' and D1.ParamValue='Adam' and
D2.ParamName='LastName' and D2.ParamValue='Smith' and
D3.ParamName='Age' and D3.ParamValue=35 and
D4.ParamName='Gender' and D4.ParamValue='M'

有一个更好的方法吗?

4

3 回答 3

6

这就是您使用EAV模式(基本上是键值对)时发生的情况

除了在(ParamName, ParamValue)for上添加索引之外,您无能为力LogDetail。这假设聚集索引保持为LogRef

于 2012-05-31T09:41:14.193 回答
1

您可以做的一件事是Index在加入子句中使用的字段上使用。

于 2012-05-31T09:38:09.603 回答
1

一种简化查询的方法是创建一个视图,将键值对聚合成更有用的东西:

CREATE VIEW ViewLogUsers
AS
SELECT UFN.LogRef, UFN.ParamName AS FirstName, ULN.ParamName AS LastName, UAG.ParamName AS Age, UGE.ParamName AS Gender
FROM LogDetail AS UFN
INNER JOIN LogDetail AS ULN ON UFN.LogRef = ULN.LogRef
INNER JOIN LogDetail AS UAG ON UFN.LogRef = UAG.LogRef
INNER JOIN LogDetail AS UGE ON UFN.LogRef = UGE.LogRef
WHERE UFN.ParamName = 'Firstname' AND ULN.ParamName = 'LastName' AND UAG.ParamName = 'Age' AND UGE.ParamName = 'Gender'
GO

然后您的原始查询变为:

SELECT 
L.*, D1.FirstName, D1.LastName, D1.Age, D1.Gender
FROM Log as L
INNER JOIN ViewLogUsers as D1 on L.Id = D1.LogRef
WHERE D1.FirstName = 'Adam' AND D1.LastName = 'Smith' AND D1.Age = '35' AND D1.Gender = 'M'

与使用与视图相同的结构的表相比,您的性能仍然会差得多(尽管如果您能够使用索引视图会有所帮助),但至少使用起来会容易得多.

于 2012-05-31T10:07:06.550 回答