我有一个基于存储过程的报告,我需要在输出中添加用户名。
在我的系统中,两个用户可以是交易的所有者。
此外,在我的系统中,用户信息存储在不同的数据库中。
因此,我仅看到两种添加用户名的方法:
案例1
SELECT
E.*,
CASE WHEN (E.UserDetailsId IS NULL AND E.UserDetailsId2 IS NULL)
THEN 'N/A'
ELSE
(SELECT CONCAT(FirstName, ' ', LastName) AS UserName
FROM UserDb.dbo.UserDetails WHERE (
(UserDetailsId IS NOT NULL AND UserDetailsId = E.UserDetailsId)
OR
(UserDetailsId2 IS NOT NULL AND UserDetailsId2 = E.UserDetailsId)
)
END AS UserName,
FROM
TransactionDetail E
WHERE
E.TransactionDetailTypeId = @TypeId
案例2
SELECT
E.*,
CASE WHEN (E.UserDetailsId IS NULL AND E.UserDetailsId2 IS NULL)
THEN 'N/A'
ELSE
CASE WHEN (E.UserDetailsId IS NOT NULL)
THEN CONCAT(UD.FirstName, ' ', UD.LastName)
CASE WHEN (E.UserDetailsId2 IS NOT NULL)
THEN CONCAT(UD2.FirstName, ' ', UD2.LastName)
END AS UserName
FROM
TransactionDetail E
JOIN UserDb.dbo.UserDetails UD ON UD.UserDetailsId = E.UserDetailsId
JOIN UserDb.dbo.UserDetails UD2 ON UD2.UserDetailsId = E.UserDetailsId
WHERE
E.TransactionDetailTypeId = @TypeId
我尝试在本地计算机上进行性能测试,该测试具有100万个测试事务和1万个用户,但是结果是相同的。
从性能的角度来看,什么是最好的方法?为什么?
真实的数据库包含大约2000万笔交易,分为10个组和10万个用户。
答案 0 :(得分:0)
可以请您尝试以下脚本吗?这应该返回与您的查询相同的结果。
请测试输出是否与您的查询相同。如果不匹配,请忽略此解决方案。
SELECT E.*,
CASE
WHEN (E.UserDetailsId IS NULL AND E.UserDetailsId2 IS NULL) THEN 'N/A'
ELSE CONCAT(FirstName, ' ', LastName)
END AS UserName
FROM TransactionDetail E
LEFT JOIN UserDetails UD
ON (E.UserDetailsId = UD.UserDetailsId)
OR (E.UserDetailsId2 = UD.UserDetailsId)
WHERE E.TransactionDetailTypeId = @TypeId
答案 1 :(得分:0)
从性能的角度和您的描述,我希望以下各项具有最佳的性能:
SELECT E.*,
(CASE WHEN E.UserDetailsId IS NOT NULL
THEN CONCAT(UD.FirstName, ' ', UD.LastName)
WHEN E.UserDetailsId2 IS NOT NULL
THEN CONCAT(UD2.FirstName, ' ', UD2.LastName),
ELSE 'N/A'
END) AS UserName
FROM TransactionDetail E LEFT JOIN
UserDb.dbo.UserDetails UD
ON UD.UserDetailsId = E.UserDetailsId LEFT JOIN
UserDb.dbo.UserDetails UD2
ON UD2.UserDetailsId = E.UserDetailsId2
WHERE E.TransactionDetailTypeId = @TypeId;
然后,您需要在TransactionDetail(TransactionDetailTypeId)
和UserDetails(UserDetailsId)
上建立索引。
在OR
条件下使用ON
可能会有两个不利影响。首先是性能。 OR
可能会降低性能。在本示例中,这可以缓解,因为WHERE
子句可能只匹配一行。
第二个是,如果同时填充了两个字段,那么您将获得两行-而且您似乎只需要一行作为交易ID。
答案 2 :(得分:0)
另一种尝试的方法:
( SELECT ... 'N/A' ...
FROM TransactionDetail E
WHERE E.TransactionDetailTypeId = @TypeId
AND E.UserDetailsId IS NULL
AND E.UserDetailsId2 IS NULL )
UNION ALL
( SELECT ... UD... ...
FROM TransactionDetail E JOIN UserDetails UD
WHERE E.TransactionDetailTypeId = @TypeId
AND E.UserDetailsId IS NOT NULL
AND E.UserDetailsId2 IS NULL )
UNION ALL
( SELECT ... UD2... ...
FROM TransactionDetail E JOIN UserDetails UD2
WHERE E.TransactionDetailTypeId = @TypeId
AND E.UserDetailsId IS NULL
AND E.UserDetailsId2 IS NOT NULL )
UNION ALL
( SELECT ... UD...UD2... ...
FROM TransactionDetail E JOIN UserDetails UD JOIN UserDetails UD2
WHERE E.TransactionDetailTypeId = @TypeId
AND E.UserDetailsId IS NOT NULL
AND E.UserDetailsId2 IS NOT NULL) )
拥有INDEX(TransactionDetailTypeId, UserDetailsId, UserDetailsId2)