'SQL Server - Optimize query

I need to use an existing SQL Server stored procedure, but in my opinion it's not optimized at all, as with no where clause it takes 45 seconds to complete with not a huge amount of data.

I know it will very difficult to test it for anyone trying to help me, but at least give me an idea or start point to improve it.

The query is the next:

DECLARE @PFK_ENTERPRISE int = 7,
        @PFK_USER int = 14118,
        @ID_REGION varchar(200) = '',
        @FK_SITE int = 0,
        @FK_MARKET int = null;

DECLARE @RETURN_TABLE TABLE
                      (
                          MARKET varchar(200),
                          NAMES varchar(200),
                          PK_IDS VARCHAR (25),
                          PFK_MARKET INT,
                          IS_ADHOC BIT
                      )

INSERT INTO @RETURN_TABLE (NAMES, PK_IDS, PFK_MARKET, IS_ADHOC, MARKET )
    SELECT DISTINCT
        CASE 
            WHEN CLIENT_LEGAL.LEGAL_NAME = CLIENT_ORIGIN.LEGAL_NAME 
                THEN CLIENT_LEGAL.LEGAL_NAME 
            ELSE CLIENT_ORIGIN.LEGAL_NAME + ' (' + CLIENT_LEGAL.LEGAL_NAME + ')' 
        END AS 'NAMES',
        CONVERT(VARCHAR(10), MARKETS_CATALOGUES.PFK_CLIENT_LEGAL) + '/' + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN) + '/'  + CONVERT(VARCHAR(10), MARKETS_CATALOGUES.PFK_COMPANY) AS 'PK_IDS',
        USER_ACCESS_CLIENTS.PFK_MARKET, 1 as "IS_ADHOC", 
        MARKET.NAME_DESCRIPTION
    FROM        
        USER_ACCESS_CLIENTS
    INNER JOIN 
        MARKETS_CATALOGUES ON USER_ACCESS_CLIENTS.PFK_ENTERPRISE = MARKETS_CATALOGUES.PFK_ENTERPRISE
                           AND USER_ACCESS_CLIENTS.PFK_MARKET = MARKETS_CATALOGUES.PFK_MARKET 
                           AND USER_ACCESS_CLIENTS.PFK_CLIENT_LEGAL = MARKETS_CATALOGUES.PFK_CLIENT_LEGAL 
                           AND USER_ACCESS_CLIENTS.PFK_CLIENT_ORIGIN = MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN  
                           AND USER_ACCESS_CLIENTS.PFK_COMPANY = MARKETS_CATALOGUES.PFK_COMPANY
    INNER JOIN 
        CLIENTS AS CLIENT_LEGAL ON MARKETS_CATALOGUES.PFK_ENTERPRISE = CLIENT_LEGAL.PFK_ENTERPRISE 
                                AND MARKETS_CATALOGUES.PFK_COMPANY = CLIENT_LEGAL.PFK_COMPANY 
                                AND MARKETS_CATALOGUES.PFK_CLIENT_LEGAL = CLIENT_LEGAL.PK_CLIENT

    INNER JOIN 
        CLIENTS AS CLIENT_ORIGIN ON MARKETS_CATALOGUES.PFK_ENTERPRISE = CLIENT_ORIGIN.PFK_ENTERPRISE 
                                 AND MARKETS_CATALOGUES.PFK_COMPANY = CLIENT_ORIGIN.PFK_COMPANY 
                                 AND MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN = CLIENT_ORIGIN.PK_CLIENT
    INNER JOIN
        MARKET ON MARKETS_CATALOGUES.PFK_ENTERPRISE = market.PFK_ENTERPRISE
               AND MARKETS_CATALOGUES.PFK_MARKET = market.PK_MARKET
    INNER JOIN 
        CATALOGUES cat ON cat.PFK_ENTERPRISE = MARKETS_CATALOGUES.PFK_ENTERPRISE 
                       AND cat.PK_CATALOGUE = MARKETS_CATALOGUES.PFK_CATALOGUE
                       AND market.FK_SITE = cat.FK_SITE
    WHERE       
        USER_ACCESS_CLIENTS.PFK_ENTERPRISE = @PFK_ENTERPRISE
        AND USER_ACCESS_CLIENTS.PFK_USER = @PFK_USER 
        AND MARKETS_CATALOGUES.FK_CATALOGUE_SETUP > 0 
        AND MARKETS_CATALOGUES.IS_ACTIVE = 1
        AND (@FK_MARKET IS NULL OR @FK_MARKET = USER_ACCESS_CLIENTS.PFK_MARKET)
        AND FK_TYPE_CATALOGUE = 6

INSERT INTO @RETURN_TABLE (NAMES, PK_IDS, PFK_MARKET, IS_ADHOC, MARKET)
    SELECT DISTINCT
        CASE WHEN CLIENT_LEGAL.LEGAL_NAME = CLIENT_ORIGIN.LEGAL_NAME THEN CLIENT_LEGAL.LEGAL_NAME ELSE CLIENT_ORIGIN.LEGAL_NAME + ' (' + CLIENT_LEGAL.LEGAL_NAME + ')' END AS 'NAMES',
        CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_LEGAL) + '/' + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN) + '/'  + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_COMPANY) AS 'PK_IDS',
        USER_ACCESS_CLIENTS.PFK_MARKET, 0 as "IS_ADHOC", 
        MARKET.NAME_DESCRIPTION AS MARKET

FROM        USER_ACCESS_CLIENTS
            inner JOIN MARKETS_CATALOGUES
                        ON USER_ACCESS_CLIENTS.PFK_ENTERPRISE = MARKETS_CATALOGUES.PFK_ENTERPRISE AND
                        USER_ACCESS_CLIENTS.PFK_MARKET = MARKETS_CATALOGUES.PFK_MARKET AND
                        USER_ACCESS_CLIENTS.PFK_CLIENT_LEGAL = MARKETS_CATALOGUES.PFK_CLIENT_LEGAL AND
                        USER_ACCESS_CLIENTS.PFK_CLIENT_ORIGIN = MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN AND
                        USER_ACCESS_CLIENTS.PFK_COMPANY = MARKETS_CATALOGUES.PFK_COMPANY
            INNER JOIN CLIENTS AS CLIENT_LEGAL 
                        ON MARKETS_CATALOGUES.PFK_ENTERPRISE = CLIENT_LEGAL.PFK_ENTERPRISE AND
                        MARKETS_CATALOGUES.PFK_COMPANY = CLIENT_LEGAL.PFK_COMPANY AND
                        MARKETS_CATALOGUES.PFK_CLIENT_LEGAL = CLIENT_LEGAL.PK_CLIENT

            INNER JOIN CLIENTS AS CLIENT_ORIGIN ON  MARKETS_CATALOGUES.PFK_ENTERPRISE = CLIENT_ORIGIN.PFK_ENTERPRISE AND

                                            MARKETS_CATALOGUES.PFK_COMPANY = CLIENT_ORIGIN.PFK_COMPANY AND

                                            MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN = CLIENT_ORIGIN.PK_CLIENT
            
            inner join MARKET on MARKETS_CATALOGUES.PFK_ENTERPRISE = market.PFK_ENTERPRISE
                                        and MARKETS_CATALOGUES.PFK_MARKET = market.PK_MARKET

            INNER JOIN CATALOGUES cat on cat.PFK_ENTERPRISE = MARKETS_CATALOGUES.PFK_ENTERPRISE and cat.PK_CATALOGUE = MARKETS_CATALOGUES.PFK_CATALOGUE
            and market.FK_SITE = cat.FK_SITE

WHERE       USER_ACCESS_CLIENTS.PFK_ENTERPRISE = @PFK_ENTERPRISE
            AND USER_ACCESS_CLIENTS.PFK_USER = @PFK_USER 
            AND MARKETS_CATALOGUES.FK_CATALOGUE_SETUP > 0 
            AND MARKETS_CATALOGUES.IS_ACTIVE = 1
            AND (@FK_MARKET IS NULL OR @FK_MARKET = USER_ACCESS_CLIENTS.PFK_MARKET)
            AND FK_TYPE_CATALOGUE <> 6
            and CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_LEGAL) + '/' + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN) + '/'  + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_COMPANY) NOT IN (select PK_IDS from @RETURN_TABLE)

            select *
            from @RETURN_TABLE
            group by PK_IDS
            order by MARKET

and the line slowing down significantly the query is:

and CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_LEGAL) + '/' + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_CLIENT_ORIGIN) + '/'  + CONVERT(VARCHAR(10),MARKETS_CATALOGUES.PFK_COMPANY) NOT IN (select PK_IDS from @RETURN_TABLE)

of course because of the NOT IN (select PK_IDS from @RETURN_TABLE) which does a select for each row, but I'm not finding a way to avoid that line, because commenting it creates duplicated records in the result temp table.

This is just an example filtering for market 231 and having commented the "offending" line i was talking, so you have a minimal idea of data returned.

adm Promotions  ADM Promotions UK Limited                           75/75/39    231 1
adm Promotions  Branding Your POS Mexico, S.A. de C.V. / BYP (MX )  107/107/39  231 1
adm Promotions  Imagen Publicitaria Punto de Venta SA de CV (MX )   111/111/39  231 1
adm Promotions  ADM Promotions UK Limited                           75/75/39    231 0
adm Promotions  Branding Your POS Mexico, S.A. de C.V. / BYP (MX )  107/107/39  231 0
adm Promotions  Imagen Publicitaria Punto de Venta SA de CV (MX )   111/111/39  231 0

So, as you see, there are two records (AD_HOC 1 and AD_HOC 0) repeated records with the same PK_IDS, but I cannot affirm the AD_HOC with value 1 or the one with value 0 can be skipped.

Not sure if you understand, but I hope anyone can help.

Attempt 1:

Doing the next in the result tmp table select could resolve in a way my issue, I remove the "offending" line (which makes an acceptable timing) and then in the result I keep only the first value from repeated ones, but tsql is underlying "seqnum" in the where stating that is incorrect. How to fix that?

SELECT 
    *, 
    ROW_NUMBER() OVER (PARTITION BY PK_IDS ORDER BY market) seqnum
FROM  
    @RETURN_TABLE 
WHERE
    seqnum = 1


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source