结合 SQL 服务器查询以提高速度

Combining SQL Server queries for speed

我有两张表,一张是需要定期检查的项目,一张是这些项目的检查报告。

如果工程师出于某种原因无法看到项目,则可以将项目标记为“无法检查”。

我需要显示项目列表,显示每个项目的最后实际 检验日期。 如果项目的最后一次实际检查与最后一次访问日期不同(即最后一次尝试检查),则需要突出显示。

这是我目前拥有的:

表和列:

Items
ID, Name, etc...

ReportItems
ReportID, ItemID, InspectionDate, NotAvailable

开始狡猾的伪代码:

SELECT * FROM Items

' then loop through that to display the data:
For each itemDataRow

  ' Get last actual date
  datatable1 = SELECT TOP 1 ReportID, InspectionDate FROM ReportItems WHERE ItemID = itemDataRow(ID) AND NotAvailable = 0 ORDER BY InspectionDate DESC

  ' Get last attempted date
  datatable2 = SELECT TOP 1 ReportID FROM ReportItems WHERE ItemID = itemDataRow(ID) ORDER BY InspectionDate DESC

  ' Check if they are the same
  itemWasNotAvailableAtLastVisit = datatable1(ReportID) <> datatable2(ReportID)

  ' add row to list to display, showing datatable1(InspectionDate), highlighted if itemWasNotAvailableAtLastVisit == true

End loop

问题在于,这意味着在填充数据时对每个项目进行 2 次额外的数据库查询,这会大大降低速度,尤其是在较长的列表中。

我该如何优化它,最好是将其优化为单个快速查询?

我试过这样的子查询,但速度很慢:

SELECT ID, Name, (
SELECT TOP 1 InspectionDate FROM ReportItems WHERE ItemID = Items.ID AND Available = 0 ORDER BY InspectionDate DESC
) AS LastInspection,
(
SELECT TOP 1 InspectionDate FROM ReportItems WHERE ItemID = Items.ID ORDER BY InspectionDate DESC
) AS LastVisit
 FROM Items

示例数据:

项目

ID | Name
---------
1  | Crane
2  | Tractor
3  | Forklift

报告项目

ReportID | VisitID | ItemID | InspectionDate | NotAvailable
----------------------------------------------------------------
1        | 1       | 1      | 2022-04-20     | 0
2        | 1       | 2      | 2022-04-20     | 1
3        | 1       | 3      | 2022-04-20     | 0
4        | 2       | 1      | 2022-03-15     | 0
5        | 2       | 2      | 2022-03-15     | 0
6        | 2       | 3      | 2022-03-15     | 0

期望的结果:

Crane, last inspection was 2022-04-20
Tractor, last inspection was **2022-03-15** (NB This is not the last visit date) 
Forklift, last inspection was 2022-04-20

根据您的示例查询,您可能 join/group/max 如下:

SELECT ID, [Name]
    , MAX(CASE WHEN Available = 0 THEN InspectionDate END) AS LastInspection
    , MAX(InspectionDate) AS LastVisit
FROM Items I
JOIN ReportItems RI on RI.ItemID = I.ID
GROUP BY I.ID;