C#程序员在这里,我的任务是在我们的一个遗留应用程序中编辑冗长的SQL Server程序,这些程序需要尽可能提高性能和高效运行。如果我的路线最适合当前的情景,我将不胜感激。
SCENARIO
由于原始设计师对代码和DB的设计,这是非正统的。对于搜索网格,我需要查看"保修文档"已根据用户选择的选项以及字符串/单词的串联值"保修"在tbl.docs
中生成或未生成。和tbl.warranty.warrantyId
值本身。
保修的价值' + tbl.warranty.warrantyId
等于tbl.docs.name
列值,不幸的是,这是加入/链接两个表的唯一方法。
每次保修可以多次生成保修文档。
参数@IsGenerated
是最终用户选择是否参与过滤的用户选项。
这里有一些填充的数据用于说明:
tbl.warranty
:
| warrantyId | name | createdDate |
|------------|-------------|-------------------------|
| 456 | Warranty 1 | 2002-04-01 12:14:53.330 |
| 1000 | Warranty 2 | 2002-04-01 12:14:53.327 |
| 1701 | Warranty 3 | 2002-04-01 12:14:53.333 |
| 2456 | Warranty 4 | 2002-04-01 12:14:53.327 |
| 3556 | Warranty 5 | 2002-04-01 12:14:53.330 |
tbl.docs
:
| docId | name | createdDate |
|------------|--------------|-------------------------|
| 1 | Warranty1000 | 2006-11-25 13:33:31.093 |
| 2 | Warranty456 | 2015-02-11 13:33:31.100 |
| 3 | Warranty1000 | 2012-05-17 13:33:31.097 |
| 4 | Warranty1000 | 2017-01-11 13:33:31.097 |
| 5 | Warranty1701 | 2017-03-14 13:33:31.100 |
| 6 | Warranty456 | 2017-03-15 13:33:31.100 |
所以你可以看到:
期望的行动/结果
用户可以选择不选择任何过滤器选项,[我需要显示所有保修记录和生成的时间(tbl.docs.createdDate),但是返回null tbl.docs.createdDate(如果愿意,还会生成日期)如果它还没有被请求生成,或者基于max tbl.docs.createdDate(generatedDate)的MOST RECENT记录(如果有的话)
| warrantyId | name | generatedDate |
|------------|--------------|-------------------------|
| 456 | Warranty 1 | 2017-03-15 13:33:31.100 |
| 1000 | Warranty 2 | 2017-01-11 13:33:31.097 |
| 1701 | Warranty 3 | 2017-03-14 13:33:31.100 |
| 2456 | Warranty 4 | NULL |
| 3556 | Warranty 5 | NULL |
用户可以过滤已为其生成文档的保证,[我需要显示所有具有doc生成记录的保修记录,基于字符串/单词"保修"和warrantyId等于docs.name值。生成多个文档的保证,我只需要最近生成的记录]
| warrantyId | name | generatedDate |
|------------|--------------|-------------------------|
| 456 | Warranty 1 | 2017-03-15 13:33:31.100 |
| 1000 | Warranty 2 | 2017-01-11 13:33:31.097 |
| 1701 | Warranty 3 | 2017-03-14 13:33:31.100 |
用户可以过滤已为其生成文档的保证,[我需要显示所有保修记录,这些保修记录尚未根据字符串/单词生成文档生成的记录"保修和"保修和"保修和"保修& #34;和warrantyId等于docs.name]
| warrantyId | name | generatedDate |
|------------|--------------|-------------------------|
| 2456 | Warranty 4 | NULL |
| 3556 | Warranty 5 | NULL |
这是我的努力。我想根据docs表创建一个临时表,并在我的查询中使用它是效率的最佳途径,而不是将此查询压低,而不是已经存在。
IF OBJECT_ID('tempdb..#tmpDocs') IS NOT NULL
DROP TABLE #tmpDocs
GO
CREATE TABLE #tmpDocs
(
createdDate datetime not null,
name varchar(30) not null
)
INSERT INTO #tmpDocs (createdDate, name)
SELECT createdDate, name
FROM docs
DECLARE @IsGenerated BIT
SET @IsGenerated = 0
SELECT
w.warrantyId,
w.name,
(SELECT TOP 1 d.createdDate
FROM #tmpDocs d
WHERE d.name = CONCAT('Warranty', w.warrantyId)
ORDER BY d.createdDate DESC) AS [generatedDate]
FROM
warranty w
WHERE
(@IsGenerated IS NULL OR @IsGenerated = 0
OR EXISTS (SELECT *
FROM #tmpDocs d
WHERE d.name = CONCAT('Warranty', w.warrantyId)))
AND (@IsGenerated IS NULL OR @IsGenerated = 1 OR
NOT EXISTS (SELECT *
FROM #tmpDocs d
WHERE d.name = CONCAT('Warranty', w.warrantyId)
)
)
)
已编辑 - ATTEMPT#2
select
w.warrantyId,
w.name,
d.createdDate as [generatedDate]
from warranty w
left join #tmpDocs d
on d.name = concat('Warranty', w.warrantyId)
AND d.createdDate = (SELECT top 1 d.createdDate
FROM #tmpDocs d
WHERE d.name = CONCAT('Warranty', w.warrantyId)
ORDER BY d.createdDate desc)
WHERE
(@IsGenerated IS NULL OR @IsGenerated = 0
OR EXISTS (SELECT *
FROM #tmpDocs d
WHERE d.name = CONCAT('Warranty', w.warrantyId))
)
AND (@IsGenerated IS NULL OR @IsGenerated = 1
OR NOT EXISTS (SELECT *
FROM #tmpDocs d
WHERE d.name = CONCAT('Warranty', w.warrantyId)
)
)
group by w.warrantyId, d.createdDate, w.name
执行时间是相同的,我猜测是因为我的小数据集我正在使用:
(5行(s)受影响)
SQL Server执行时间: CPU时间= 0 ms,经过时间= 0 ms。
(5行(s)受影响)
SQL Server执行时间: CPU时间= 0 ms,经过时间= 0 ms。
非常感谢您阅读此内容等。如果有其他途径(不使用CTE,因为这只是proc的一个简单方面,我将进行编辑,我不会有在那个时候重构整个事情的时间),我很乐意听到它。执行此程序不能陷入困境。
答案 0 :(得分:0)
这绝对不是最佳选择。如果您有任何电源,最佳解决方案是更新doc表并将保修ID添加为单独的列,与保修表的保修ID相同的数据类型。如果这不是一个选项,另一个解决方案是打破两个查询(一个用于文档,一个用于保证),并让应用程序生成IN子句以包含文档名称。
至于在应用程序代码中可以更好地处理的过滤。
以下查询将为您提供所需的内容,但不太确定性能,而实际上无法自行运行对db的查询。
SELECT
w.warrantyId,
MAX(w.name) as name,
MAX(d.createdDate) as generatedDate
FROM warranty w
LEFT JOIN docs d on d.Name = CONCAT('Warranty', w.warrantyId)
GROUP BY w.warrantyId