Sql查询IN子句限制1条记录
Sql Query IN clause limit 1 Record
我有一个查询,我在其中使用 IN 子句(对于 2 列,251 和 252)从表中获取记录。在理想情况下,251 或 252 都有值,因此它应该可以正常工作,但在某些情况下,某些作业可能同时具有 251 或 252 值,但我只需要根据 jobHistoryID(最大值)限制 1 条记录。通过下面的查询,我有时会得到 2,如果我在 Left Join 中使用 Top 1,它会得到 null
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[CustomerReadyDate].[JobHistoryDate] As [ConfirmLeadDate1],
[CustomerReadyDate].[JobColumnID]
FROM
[tblJob] Job
ON [Job].[JobID] = [StepJob].[JobID]
AND [Job].[SubmitTimestamp] > '2019-01-01'
LEFT JOIN (
SELECT
[JobHistory].[JobID],
[JobHistory].[JobHistoryDate],
[JobHistory].[JobColumnID],
[JobHistory].[JobHistoryID],
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE
[JobHistory].[jobColumnID] IN (251,252)
) AS [CustomerReadyDate]
ON [CustomerReadyDate].[JobID] = [Job].[JobID]
WHERE
[Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
您可以在 jobHistoryID
的基础上添加一个 ROW_NUMBER()
函数
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[CustomerReadyDate].[JobHistoryDate] As [ConfirmLeadDate1],
[CustomerReadyDate].[JobColumnID]
FROM
[tblJob] Job
ON [Job].[JobID] = [StepJob].[JobID]
AND [Job].[SubmitTimestamp] > '2019-01-01'
LEFT JOIN (
SELECT
[JobHistory].[JobID],
[JobHistory].[JobHistoryDate],
[JobHistory].[JobColumnID],
[JobHistory].[JobHistoryID],
ROW_NUMBER() OVER(ORDER BY [JobHistoryID] DESC) rn
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE
[JobHistory].[jobColumnID] IN (251,252)
) AS [CustomerReadyDate]
ON [CustomerReadyDate].[JobID] = [Job].[JobID]
WHERE
[Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
AND [CustomerReadyDate].rn = 1
但我认为您可以优化您的查询,如下所示:
SELECT * FROM (
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[JobHistory].[JobHistoryDate] As [ConfirmLeadDate1],
[JobHistory].[JobColumnID]
ROW_NUMBER() OVER(ORDER BY [JobHistoryID] DESC) rn
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE [JobHistory].[jobColumnID] IN (251,252)
AND [Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
) AS T1
WHERE T1.rn = 1
也许您可以 LEFT JOIN 历史 table 并获取按日期排序的第一条记录。
;WITH Data AS
(
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[CustomerReadyDate].[JobHistoryDate] As [ConfirmLeadDate1],
[CustomerReadyDate].[JobColumnID],
Instance = ROW_NUMBER() OVER(PARTITION BY Job.JobId ORDER BY [CustomerReadyDate.JobHistoryDate] DESC)
FROM
[tblJob] Job
ON [Job].[JobID] = [StepJob].[JobID]
AND [Job].[SubmitTimestamp] > '2019-01-01'
LEFT JOIN [dbo].[JobHistory] AS [CustomerReadyDate]
ON [Job].[JobID] = [CustomerReadyDate].[JobID] AND [CustomerReadyDate].[jobColumnID] IN (251,252)
WHERE
[Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
)
SELECT
JobID,
ConfirmLeadDate1,
JobColumnID
FROM
Data D
WHERE
Instance = 1
您似乎对查询进行了多次重写以使其正常工作,并且引入了一些冗余(即在最内部子查询中使用 tblJob
进行冗余连接)。尝试以下查询使其工作。
SELECT *
FROM (
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber]
[JobHistory].[JobHistoryDate],
[JobHistory].[JobColumnID],
row_number() over (partition by [Job].[JobID] order by [JobHistory].[JobHistoryID] desc) AS [rn]
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE
[JobHistory].[JobColumnID] IN (251,252) AND
[Job].[SubmitTimestamp] > '2019-01-01' AND
[Job].[OrderType] = 'Job' AND
[Job].LocationTypeID = 1
) t
WHERE t.[rn] = 1
使用OUTER APPLY
:
FROM [tblJob] Job
ON [Job].[JobID] = [StepJob].[JobID] AND
[Job].[SubmitTimestamp] > '2019-01-01' OUTER APPLY
(SELECT TOP (1) [JobHistory].[JobID], [JobHistory].[JobHistoryDate],
[JobHistory].[JobColumnID], [JobHistory].[JobHistoryID],
FROM [dbo].[tblJob_History] [JobHistory]
WHERE [Job].[JobID] = [JobHistory].[JobID] AND
[JobHistory].[jobColumnID] IN (251, 252)
ORDER BY JobHistory.JobHistoryId DESC
) [CustomerReadyDate]
您还会注意到,这会删除子查询中的 JOIN
到 tblJob
,因为这并不是真正必要的。
我有一个查询,我在其中使用 IN 子句(对于 2 列,251 和 252)从表中获取记录。在理想情况下,251 或 252 都有值,因此它应该可以正常工作,但在某些情况下,某些作业可能同时具有 251 或 252 值,但我只需要根据 jobHistoryID(最大值)限制 1 条记录。通过下面的查询,我有时会得到 2,如果我在 Left Join 中使用 Top 1,它会得到 null
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[CustomerReadyDate].[JobHistoryDate] As [ConfirmLeadDate1],
[CustomerReadyDate].[JobColumnID]
FROM
[tblJob] Job
ON [Job].[JobID] = [StepJob].[JobID]
AND [Job].[SubmitTimestamp] > '2019-01-01'
LEFT JOIN (
SELECT
[JobHistory].[JobID],
[JobHistory].[JobHistoryDate],
[JobHistory].[JobColumnID],
[JobHistory].[JobHistoryID],
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE
[JobHistory].[jobColumnID] IN (251,252)
) AS [CustomerReadyDate]
ON [CustomerReadyDate].[JobID] = [Job].[JobID]
WHERE
[Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
您可以在 jobHistoryID
ROW_NUMBER()
函数
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[CustomerReadyDate].[JobHistoryDate] As [ConfirmLeadDate1],
[CustomerReadyDate].[JobColumnID]
FROM
[tblJob] Job
ON [Job].[JobID] = [StepJob].[JobID]
AND [Job].[SubmitTimestamp] > '2019-01-01'
LEFT JOIN (
SELECT
[JobHistory].[JobID],
[JobHistory].[JobHistoryDate],
[JobHistory].[JobColumnID],
[JobHistory].[JobHistoryID],
ROW_NUMBER() OVER(ORDER BY [JobHistoryID] DESC) rn
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE
[JobHistory].[jobColumnID] IN (251,252)
) AS [CustomerReadyDate]
ON [CustomerReadyDate].[JobID] = [Job].[JobID]
WHERE
[Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
AND [CustomerReadyDate].rn = 1
但我认为您可以优化您的查询,如下所示:
SELECT * FROM (
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[JobHistory].[JobHistoryDate] As [ConfirmLeadDate1],
[JobHistory].[JobColumnID]
ROW_NUMBER() OVER(ORDER BY [JobHistoryID] DESC) rn
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE [JobHistory].[jobColumnID] IN (251,252)
AND [Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
) AS T1
WHERE T1.rn = 1
也许您可以 LEFT JOIN 历史 table 并获取按日期排序的第一条记录。
;WITH Data AS
(
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber],
[CustomerReadyDate].[JobHistoryDate] As [ConfirmLeadDate1],
[CustomerReadyDate].[JobColumnID],
Instance = ROW_NUMBER() OVER(PARTITION BY Job.JobId ORDER BY [CustomerReadyDate.JobHistoryDate] DESC)
FROM
[tblJob] Job
ON [Job].[JobID] = [StepJob].[JobID]
AND [Job].[SubmitTimestamp] > '2019-01-01'
LEFT JOIN [dbo].[JobHistory] AS [CustomerReadyDate]
ON [Job].[JobID] = [CustomerReadyDate].[JobID] AND [CustomerReadyDate].[jobColumnID] IN (251,252)
WHERE
[Job].[OrderType] = 'Job'
AND [Job].LocationTypeID = 1
)
SELECT
JobID,
ConfirmLeadDate1,
JobColumnID
FROM
Data D
WHERE
Instance = 1
您似乎对查询进行了多次重写以使其正常工作,并且引入了一些冗余(即在最内部子查询中使用 tblJob
进行冗余连接)。尝试以下查询使其工作。
SELECT *
FROM (
SELECT
[Job].[JobID],
[Job].[PriceEstimateNumber]
[JobHistory].[JobHistoryDate],
[JobHistory].[JobColumnID],
row_number() over (partition by [Job].[JobID] order by [JobHistory].[JobHistoryID] desc) AS [rn]
FROM [dbo].[tblJob_History] AS [JobHistory]
INNER JOIN [dbo].[tblJob] AS [Job]
ON [Job].[JobID] = [JobHistory].[JobID]
WHERE
[JobHistory].[JobColumnID] IN (251,252) AND
[Job].[SubmitTimestamp] > '2019-01-01' AND
[Job].[OrderType] = 'Job' AND
[Job].LocationTypeID = 1
) t
WHERE t.[rn] = 1
使用OUTER APPLY
:
FROM [tblJob] Job
ON [Job].[JobID] = [StepJob].[JobID] AND
[Job].[SubmitTimestamp] > '2019-01-01' OUTER APPLY
(SELECT TOP (1) [JobHistory].[JobID], [JobHistory].[JobHistoryDate],
[JobHistory].[JobColumnID], [JobHistory].[JobHistoryID],
FROM [dbo].[tblJob_History] [JobHistory]
WHERE [Job].[JobID] = [JobHistory].[JobID] AND
[JobHistory].[jobColumnID] IN (251, 252)
ORDER BY JobHistory.JobHistoryId DESC
) [CustomerReadyDate]
您还会注意到,这会删除子查询中的 JOIN
到 tblJob
,因为这并不是真正必要的。