简体   繁体   中英

Sql Query IN clause limit 1 Record

I have a query where I am using IN clause (for 2 columns, 251 and 252) to get records from tables. In ideal case, either 251 or 252 will have value, so it should work fine, but in some cases, some jobs may have both 251 or 252 value, but I need to only limit 1 record based on jobHistoryID (max value). With below query, I get sometimes 2 and if I use Top 1 in Left Join, it gets me 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

You can add a ROW_NUMBER() function based on the jobHistoryID

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

but i think you can optimize you query as the following:

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 

Perhaps you can LEFT JOIN The history table and take the first record ordered by date.

;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    

It seems that you have done many rewritings into your query in order to make it work and you have introduced some redundancy (ie redundant join with tblJob in the most inner subquery). Try the following query to make it work.

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

Use 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]

You'll also notice that this removes the JOIN to tblJob in the subquery, because that is not really necessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM