Substring join or additional table, which is faster?Which is faster joinSQL to select random mix of rows fairlyAltering strings while selecting themSQL Server: CONVERT From ISO8601 To DateTime Within QuerySingle year column and multiple weeks columns into single year/week column with PIVOTSearching multiple tables in SQLTransposing hierachical data from one VARCHAR to two INTsSSRS --> .xlsx file --> SQL ETL — “External table not in expected format” error, but only when files have not been openedHow to Know if I have A Restricted or Full Access to TableHow to store hierarchical dimension for timeseries data

Addressing an email

How was the blinking terminal cursor invented?

How to plot a surface from a system of equations?

Would it be possible to set up a franchise in the ancient world?

How can I prevent Bash expansion from passing files starting with "-" as argument?

Cycling to work - 30 mile return

What were the "pills" that were added to solid waste in Apollo 7?

Why didn't Daenerys' advisers suggest assassinating Cersei?

Why does string strummed with finger sound different from the one strummed with pick?

Why would Thor need to strike a building with lightning to attack enemies?

What city and town structures are important in a low fantasy medieval world?

FIFO data structure in pure C

Warped chessboard

Will this series of events work to drown the Tarrasque?

What does it mean for a program to be 32 or 64 bit?

What should I wear to go and sign an employment contract?

Why does the U.S military use mercenaries?

Head-internal relative clauses

Should I twist DC power and ground wires from a power supply?

Bash - Execute two commands and get exit status 1 if first fails

On a piano, are the effects of holding notes and the sustain pedal the same for a single chord?

What does this 'x' mean on the stem of the voice's note, above the notehead?

Are there any crystals that are theoretically possible, but haven't yet been made?

Windows reverting changes made by Linux to FAT32 partition



Substring join or additional table, which is faster?


Which is faster joinSQL to select random mix of rows fairlyAltering strings while selecting themSQL Server: CONVERT From ISO8601 To DateTime Within QuerySingle year column and multiple weeks columns into single year/week column with PIVOTSearching multiple tables in SQLTransposing hierachical data from one VARCHAR to two INTsSSRS --> .xlsx file --> SQL ETL — “External table not in expected format” error, but only when files have not been openedHow to Know if I have A Restricted or Full Access to TableHow to store hierarchical dimension for timeseries data






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








6















I have a case that come up regularly at work. I have many tables that use a 4 character string as a foreign key : G191



The G is a sort of category, the 19 is the year, and the 1 is an instance.
Getting all rows of category G is something we do very often. Usually like:



SELECT * FROM [Table] 
WHERE Left([ID], 1) = 'G'


There is a way to get this effect without manipulating a string, by joining to a table where this category is defined:



SELECT * FROM [Table]
JOIN [Categories] ON [Table].CategoryID = [Categories].CategoryID
WHERE [Categories].Letter = 'G'


My co worker insists that the first way is more performant, and rolls his eyes at me for doing it the second way.



Which one is better? Does joining by another table really add more work then checking the first character of a string?










share|improve this question







New contributor



SpeedOfRound is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.














  • 4





    Have you tried comparing actual run times of both queries? If not, why?

    – mustaccio
    May 13 at 18:42

















6















I have a case that come up regularly at work. I have many tables that use a 4 character string as a foreign key : G191



The G is a sort of category, the 19 is the year, and the 1 is an instance.
Getting all rows of category G is something we do very often. Usually like:



SELECT * FROM [Table] 
WHERE Left([ID], 1) = 'G'


There is a way to get this effect without manipulating a string, by joining to a table where this category is defined:



SELECT * FROM [Table]
JOIN [Categories] ON [Table].CategoryID = [Categories].CategoryID
WHERE [Categories].Letter = 'G'


My co worker insists that the first way is more performant, and rolls his eyes at me for doing it the second way.



Which one is better? Does joining by another table really add more work then checking the first character of a string?










share|improve this question







New contributor



SpeedOfRound is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.














  • 4





    Have you tried comparing actual run times of both queries? If not, why?

    – mustaccio
    May 13 at 18:42













6












6








6








I have a case that come up regularly at work. I have many tables that use a 4 character string as a foreign key : G191



The G is a sort of category, the 19 is the year, and the 1 is an instance.
Getting all rows of category G is something we do very often. Usually like:



SELECT * FROM [Table] 
WHERE Left([ID], 1) = 'G'


There is a way to get this effect without manipulating a string, by joining to a table where this category is defined:



SELECT * FROM [Table]
JOIN [Categories] ON [Table].CategoryID = [Categories].CategoryID
WHERE [Categories].Letter = 'G'


My co worker insists that the first way is more performant, and rolls his eyes at me for doing it the second way.



Which one is better? Does joining by another table really add more work then checking the first character of a string?










share|improve this question







New contributor



SpeedOfRound is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I have a case that come up regularly at work. I have many tables that use a 4 character string as a foreign key : G191



The G is a sort of category, the 19 is the year, and the 1 is an instance.
Getting all rows of category G is something we do very often. Usually like:



SELECT * FROM [Table] 
WHERE Left([ID], 1) = 'G'


There is a way to get this effect without manipulating a string, by joining to a table where this category is defined:



SELECT * FROM [Table]
JOIN [Categories] ON [Table].CategoryID = [Categories].CategoryID
WHERE [Categories].Letter = 'G'


My co worker insists that the first way is more performant, and rolls his eyes at me for doing it the second way.



Which one is better? Does joining by another table really add more work then checking the first character of a string?







sql-server sql-server-2014






share|improve this question







New contributor



SpeedOfRound is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










share|improve this question







New contributor



SpeedOfRound is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








share|improve this question




share|improve this question






New contributor



SpeedOfRound is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








asked May 13 at 17:09









SpeedOfRoundSpeedOfRound

1363




1363




New contributor



SpeedOfRound is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




New contributor




SpeedOfRound is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









  • 4





    Have you tried comparing actual run times of both queries? If not, why?

    – mustaccio
    May 13 at 18:42












  • 4





    Have you tried comparing actual run times of both queries? If not, why?

    – mustaccio
    May 13 at 18:42







4




4





Have you tried comparing actual run times of both queries? If not, why?

– mustaccio
May 13 at 18:42





Have you tried comparing actual run times of both queries? If not, why?

– mustaccio
May 13 at 18:42










1 Answer
1






active

oldest

votes


















14














Why Yours Is Better



In general, your pattern is a better idea.



Performance will depend on indexes, predicate selectivity, and table size though.



The reason your pattern is a better idea comes down to the concept of SARGability, which is a fancy word for if your search arguments can be used as seek predicates, or even fully pushed predicates, (i.e. not being processed in Filter operators after accessing an index).



Some examples of where this can hurt in joins and where clauses are:



  • function(column) = something

  • column + column = something

  • column + value = something

  • column = @something or @something IS NULL

  • column like ‘%something%’

  • column = case when …

When you do stuff like this, your queries can end up with all sorts of bad side effects:



  • Increased CPU (burn baby burn)

  • Index Scans (when you could have Seeks)

  • Implicit Conversion (if your predicates produce a different data type)

  • Poor Cardinality Estimates (poking the optimizer in the eye)

  • Inappropriate Plan Choices (because the optimizer is blind now, you jerk)

  • Long Running Queries (yay job security!)

Better Options



SARGable options for what you're looking for would include:



WHERE [ID] LIKE 'G%'



or



WHERE [ID] >= 'G' AND [ID] < 'H'



An alternative solution would be to add a computed column in just the table you're searching:



ALTER TABLE [Table] 
ADD Lefty AS Left([ID], 1);

CREATE INDEX ix_whatever
ON [Table] (CategoryID , Lefty);


Though like I said before, the performance difference may not be dramatic with smaller tables.



It's also possible that this index won't be used since your example query is selecting all of the table columns, and this index doesn't cover them. But that's a story for a different day.






share|improve this answer

























    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "182"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );






    SpeedOfRound is a new contributor. Be nice, and check out our Code of Conduct.









    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f238042%2fsubstring-join-or-additional-table-which-is-faster%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    14














    Why Yours Is Better



    In general, your pattern is a better idea.



    Performance will depend on indexes, predicate selectivity, and table size though.



    The reason your pattern is a better idea comes down to the concept of SARGability, which is a fancy word for if your search arguments can be used as seek predicates, or even fully pushed predicates, (i.e. not being processed in Filter operators after accessing an index).



    Some examples of where this can hurt in joins and where clauses are:



    • function(column) = something

    • column + column = something

    • column + value = something

    • column = @something or @something IS NULL

    • column like ‘%something%’

    • column = case when …

    When you do stuff like this, your queries can end up with all sorts of bad side effects:



    • Increased CPU (burn baby burn)

    • Index Scans (when you could have Seeks)

    • Implicit Conversion (if your predicates produce a different data type)

    • Poor Cardinality Estimates (poking the optimizer in the eye)

    • Inappropriate Plan Choices (because the optimizer is blind now, you jerk)

    • Long Running Queries (yay job security!)

    Better Options



    SARGable options for what you're looking for would include:



    WHERE [ID] LIKE 'G%'



    or



    WHERE [ID] >= 'G' AND [ID] < 'H'



    An alternative solution would be to add a computed column in just the table you're searching:



    ALTER TABLE [Table] 
    ADD Lefty AS Left([ID], 1);

    CREATE INDEX ix_whatever
    ON [Table] (CategoryID , Lefty);


    Though like I said before, the performance difference may not be dramatic with smaller tables.



    It's also possible that this index won't be used since your example query is selecting all of the table columns, and this index doesn't cover them. But that's a story for a different day.






    share|improve this answer





























      14














      Why Yours Is Better



      In general, your pattern is a better idea.



      Performance will depend on indexes, predicate selectivity, and table size though.



      The reason your pattern is a better idea comes down to the concept of SARGability, which is a fancy word for if your search arguments can be used as seek predicates, or even fully pushed predicates, (i.e. not being processed in Filter operators after accessing an index).



      Some examples of where this can hurt in joins and where clauses are:



      • function(column) = something

      • column + column = something

      • column + value = something

      • column = @something or @something IS NULL

      • column like ‘%something%’

      • column = case when …

      When you do stuff like this, your queries can end up with all sorts of bad side effects:



      • Increased CPU (burn baby burn)

      • Index Scans (when you could have Seeks)

      • Implicit Conversion (if your predicates produce a different data type)

      • Poor Cardinality Estimates (poking the optimizer in the eye)

      • Inappropriate Plan Choices (because the optimizer is blind now, you jerk)

      • Long Running Queries (yay job security!)

      Better Options



      SARGable options for what you're looking for would include:



      WHERE [ID] LIKE 'G%'



      or



      WHERE [ID] >= 'G' AND [ID] < 'H'



      An alternative solution would be to add a computed column in just the table you're searching:



      ALTER TABLE [Table] 
      ADD Lefty AS Left([ID], 1);

      CREATE INDEX ix_whatever
      ON [Table] (CategoryID , Lefty);


      Though like I said before, the performance difference may not be dramatic with smaller tables.



      It's also possible that this index won't be used since your example query is selecting all of the table columns, and this index doesn't cover them. But that's a story for a different day.






      share|improve this answer



























        14












        14








        14







        Why Yours Is Better



        In general, your pattern is a better idea.



        Performance will depend on indexes, predicate selectivity, and table size though.



        The reason your pattern is a better idea comes down to the concept of SARGability, which is a fancy word for if your search arguments can be used as seek predicates, or even fully pushed predicates, (i.e. not being processed in Filter operators after accessing an index).



        Some examples of where this can hurt in joins and where clauses are:



        • function(column) = something

        • column + column = something

        • column + value = something

        • column = @something or @something IS NULL

        • column like ‘%something%’

        • column = case when …

        When you do stuff like this, your queries can end up with all sorts of bad side effects:



        • Increased CPU (burn baby burn)

        • Index Scans (when you could have Seeks)

        • Implicit Conversion (if your predicates produce a different data type)

        • Poor Cardinality Estimates (poking the optimizer in the eye)

        • Inappropriate Plan Choices (because the optimizer is blind now, you jerk)

        • Long Running Queries (yay job security!)

        Better Options



        SARGable options for what you're looking for would include:



        WHERE [ID] LIKE 'G%'



        or



        WHERE [ID] >= 'G' AND [ID] < 'H'



        An alternative solution would be to add a computed column in just the table you're searching:



        ALTER TABLE [Table] 
        ADD Lefty AS Left([ID], 1);

        CREATE INDEX ix_whatever
        ON [Table] (CategoryID , Lefty);


        Though like I said before, the performance difference may not be dramatic with smaller tables.



        It's also possible that this index won't be used since your example query is selecting all of the table columns, and this index doesn't cover them. But that's a story for a different day.






        share|improve this answer















        Why Yours Is Better



        In general, your pattern is a better idea.



        Performance will depend on indexes, predicate selectivity, and table size though.



        The reason your pattern is a better idea comes down to the concept of SARGability, which is a fancy word for if your search arguments can be used as seek predicates, or even fully pushed predicates, (i.e. not being processed in Filter operators after accessing an index).



        Some examples of where this can hurt in joins and where clauses are:



        • function(column) = something

        • column + column = something

        • column + value = something

        • column = @something or @something IS NULL

        • column like ‘%something%’

        • column = case when …

        When you do stuff like this, your queries can end up with all sorts of bad side effects:



        • Increased CPU (burn baby burn)

        • Index Scans (when you could have Seeks)

        • Implicit Conversion (if your predicates produce a different data type)

        • Poor Cardinality Estimates (poking the optimizer in the eye)

        • Inappropriate Plan Choices (because the optimizer is blind now, you jerk)

        • Long Running Queries (yay job security!)

        Better Options



        SARGable options for what you're looking for would include:



        WHERE [ID] LIKE 'G%'



        or



        WHERE [ID] >= 'G' AND [ID] < 'H'



        An alternative solution would be to add a computed column in just the table you're searching:



        ALTER TABLE [Table] 
        ADD Lefty AS Left([ID], 1);

        CREATE INDEX ix_whatever
        ON [Table] (CategoryID , Lefty);


        Though like I said before, the performance difference may not be dramatic with smaller tables.



        It's also possible that this index won't be used since your example query is selecting all of the table columns, and this index doesn't cover them. But that's a story for a different day.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited May 13 at 21:29

























        answered May 13 at 17:38









        Erik DarlingErik Darling

        23.6k1373117




        23.6k1373117




















            SpeedOfRound is a new contributor. Be nice, and check out our Code of Conduct.









            draft saved

            draft discarded


















            SpeedOfRound is a new contributor. Be nice, and check out our Code of Conduct.












            SpeedOfRound is a new contributor. Be nice, and check out our Code of Conduct.











            SpeedOfRound is a new contributor. Be nice, and check out our Code of Conduct.














            Thanks for contributing an answer to Database Administrators Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f238042%2fsubstring-join-or-additional-table-which-is-faster%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

            Circuit construction for execution of conditional statements using least significant bitHow are two different registers being used as “control”?How exactly is the stated composite state of the two registers being produced using the $R_zz$ controlled rotations?Efficiently performing controlled rotations in HHLWould this quantum algorithm implementation work?How to prepare a superposed states of odd integers from $1$ to $sqrtN$?Why is this implementation of the order finding algorithm not working?Circuit construction for Hamiltonian simulationHow can I invert the least significant bit of a certain term of a superposed state?Implementing an oracleImplementing a controlled sum operation

            Magento 2 “No Payment Methods” in Admin New OrderHow to integrate Paypal Express Checkout with the Magento APIMagento 1.5 - Sales > Order > edit order and shipping methods disappearAuto Invoice Check/Money Order Payment methodAdd more simple payment methods?Shipping methods not showingWhat should I do to change payment methods if changing the configuration has no effects?1.9 - No Payment Methods showing upMy Payment Methods not Showing for downloadable/virtual product when checkout?Magento2 API to access internal payment methodHow to call an existing payment methods in the registration form?