我有一个大型SQL查询,我需要选择一些数据。
SELECT p.Id, p.UserId, u.Name AS CreatedBy, p.JournalId, p.Title, pt.Name AS PublicationType, p.CreatedDate, p.MagazineTitle, /*ps.StatusId,*/ p.Authors, pb.Name AS Publisher, p.Draft,jns.Name AS JournalTitle,
ISNULL(
ISNULL(
(SELECT StatusId FROM [PublicationsStatus] WHERE StatusDate=
(SELECT MAX(StatusDate) FROM [PublicationsStatus] AS ps WHERE ps.PublicationId = p.Id )),--AND ps.UserId = @UserId ORDER BY StatusDate DESC),
(SELECT TOP(1) ActionId + 6 FROM [PublicationsQuoteSaleLines] AS pqsl WHERE pqsl.PublicationId = p.Id ORDER BY pqsl.Id)
),
1
)AS StatusId
,ISNULL(
(SELECT MAX(StatusDate) FROM [PublicationsStatus] AS ps WHERE ps.PublicationId = p.Id ),--AND ps.UserId = @UserId),
p.CreatedDate
) AS StatusDate
,ISNULL(
(cast((SELECT MAX(StatusDate) FROM [PublicationsStatus] AS ps WHERE ps.PublicationId = p.Id) as date) ),--AND ps.UserId = @UserId),
p.CreatedDate
) AS StDate
,CASE
WHEN ISNULL(
ISNULL(
(SELECT StatusId FROM [PublicationsStatus] WHERE StatusDate=
(SELECT MAX(StatusDate) FROM [PublicationsStatus] AS ps WHERE ps.PublicationId = p.Id )),--AND ps.UserId = @UserId ORDER BY StatusDate DESC),
(SELECT TOP(1) ActionId + 6 FROM [PublicationsQuoteSaleLines] AS pqsl WHERE pqsl.PublicationId = p.Id ORDER BY pqsl.Id)
),
1 ) IN (1, 7, 8) THEN 0
ELSE 1 END AS OrderCriteria
,(SELECT COUNT(*) FROM SentEmails AS se WHERE se.PublicationId = p.Id AND se.EmailType = 1 AND se.UserId = @UserId) AS NumberOfAlerts
,(SELECT COUNT(*) FROM SentEmails AS se WHERE se.PublicationId = p.Id AND se.EmailType = 3 AND se.UserId = @UserId) AS NumberOfReminders
FROM Publications AS p
LEFT JOIN PublicationTypes AS pt ON p.PublicationTypeId = pt.Id
LEFT JOIN Publishers AS pb ON p.PublisherId = pb.Id
LEFT JOIN Journals As jns ON p.JournalId = jns.Id
LEFT JOIN Users AS u ON u.Id = p.UserId
问题是查询很慢。如你所见,我在OrderCriteria和StatusId上有同样的东西。 StatusDate我来自同一张桌子。 我认为我可以解决性能只能制作一个\
LEFT JOIN
类似的东西:
LEFT JOIN (
SELECT
PublicationId,
StatusId AS StatusId,
StatusDate AS StatusDate
FROM [PublicationsStatus] WHERE StatusDate=
(
SELECT MAX(StatusDate) FROM PublicationsStatus
)
) AS ps ON ps.PublicationId = p.Id
但是我没有这样得到相同的结果。 你能给些建议么?
答案 0 :(得分:0)
我尝试使用一些CTE简化您的查询,以避免多次执行相同的子查询。你可以尝试一下,看看它是否仍然很慢。
;WITH MaxStatusDateByPublication AS
(
SELECT
PublicationId = ps.PublicationId,
MaxStatusDate = MAX(ps.StatusDate)
FROM
[PublicationsStatus] AS ps
GROUP BY
PS.PublicationId
),
StatusForMaxDateByPublication AS
(
SELECT
StatusId = PS.StatusId,
M.PublicationId,
M.MaxStatusDate
FROM
MaxStatusDateByPublication AS M
INNER JOIN [PublicationsStatus] AS PS ON
M.PublicationId = PS.PublicationId AND
M.MaxStatusDate = PS.StatusDate
),
SentEmailsByPublicationAndType AS
(
SELECT
S.PublicationID,
S.EmailType,
AmountSentEmails = COUNT(1)
FROM
SentEmails AS S
WHERE
S.EmailType IN (1, 3) AND
S.UserID = @UserId
GROUP BY
S.PublicationID,
S.EmailType
)
SELECT
p.Id,
p.UserId,
u.Name AS CreatedBy,
p.JournalId,
p.Title,
pt.Name AS PublicationType,
p.CreatedDate,
p.MagazineTitle,
p.Authors,
pb.Name AS Publisher,
p.Draft,
jns.Name AS JournalTitle,
COALESCE(MS.StatusId, SL.StatusId, 1) AS StatusId,
ISNULL(MS.MaxStatusDate, P.CreatedDate) AS StatusDate,
ISNULL(CONVERT(DATE, MS.MaxStatusDate), P.CreatedDate) AS StDate,
CASE
WHEN COALESCE(MS.StatusId, SL.StatusId, 1) IN (1, 7, 8) THEN 0
ELSE 1
END AS OrderCriteria,
ISNULL(TY1.AmountSentEmails, 0) AS NumberOfAlerts,
ISNULL(TY3.AmountSentEmails, 0) AS NumberOfReminders
FROM
Publications AS p
LEFT JOIN PublicationTypes AS pt ON p.PublicationTypeId = pt.Id
LEFT JOIN Publishers AS pb ON p.PublisherId = pb.Id
LEFT JOIN Journals As jns ON p.JournalId = jns.Id
LEFT JOIN Users AS u ON u.Id = p.UserId
LEFT JOIN StatusForMaxDateByPublication AS MS ON P.Id = MS.PublicationId
LEFT JOIN SentEmailsByPublicationAndType AS TY1 ON
P.Id = TE.PublicationID AND
TY1.EmailType = 1
LEFT JOIN SentEmailsByPublicationAndType AS TY3 ON
P.Id = TE.PublicationID AND
TY1.EmailType = 3
OUTER APPLY (
SELECT TOP 1
StatusId = ActionId + 6
FROM
[PublicationsQuoteSaleLines] AS pqsl
WHERE
pqsl.PublicationId = P.Id
ORDER BY
pqsl.Id ASC) AS SL
尽量避免多次写入相同的表达式(特别是如果它在列中放入子查询!)。使用一些CTE和正确识别将有助于提高可读性。
这是一个复杂的查询,涉及多个表。如果您的查询运行缓慢,可能有许多不同的原因。尝试自己执行每个子查询以检查它们是否很慢,然后尝试将它们1加1加入。如果连接列的索引不存在,那么可能 可以提高性能。发布完整的查询执行计划可能会有所帮助。