我99%肯定这个问题已被问过100次,但我找不到任何关于最佳方法的事情。
我有一个名为People的表,然后是一个名为Jobs的表,用于存储他们所有的工作经历。
在创建报告,仪表板等时我们想要列出每个人及其最后3个工作(例如),这种情况经常出现:
John Smith
等
一些伪代码是VBish:
SELECT PersonID, Name FROM People
Do While datareaderPeople.Read()
Response.write(datareaderPeople("Name")
'SELECT TOP 3 PersonID, JobID, CompanyName, OtherFields FROM Jobs WHERE PersonID = datareaderPeople("PersonID") ORDER BY SomeDateField
Do While datareaderJobs.Read()
Response.write(datareaderJobs("CompanyName"))
End While
End While
正如您所看到的那样,我们正在进行另一个查询,以便在我们遍历各个人时为每个人获取工作。有一个更好的方法吗?这种方式似乎效率低下并且会产生大量的数据库查询。
或者,如果有人能指出我之前提出的这个问题,那也会很好。
感谢。
编辑:我正在使用上面的方法,因为我需要能够为我回来的每个作业行的作业字段做一些事情。就像格式化日期,加粗公司名称等一样。只需将工作字段合并为1个大字符串的大行就行了。
答案 0 :(得分:2)
假设SQL Server 2005
或更高:
SELECT *
FROM people p
OUTER APPLY
(
SELECT TOP 3 *
FROM job j
WHERE j.personId = p.id
ORDER BY
j.applicationDate DESC
) j
或者这个:
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY j.appicationDate DESC) AS rn
FROM people p
LEFT JOIN
job j
ON j.personId = p.id
) q
WHERE rn <= 3
答案 1 :(得分:1)
我建议您执行以下操作,它将只有2个数据库调用
SELECT PersonID, Name FROM People
SELECT PersonID, JobID, CompanyName, OtherFields FROM Jobs
Do While datareaderPeople.Read()
Response.write(datareaderPeople("Name")
Filter Jobs records data with DataView using RowFilter = "PersonID = " + datareaderPeople("PersonID")
Do While FilteredRows.Read()
Response.write(FilteredRows("CompanyName"))
End While
End While