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

If a person had control of every single cell of their body, would they be able to transform into another creature?

Why do most published works in medical imaging try to reduce false positives?

Where have Brexit voters gone?

How to use " shadow " in pstricks?

Writing with dry erase marker on Shabbos, is it permitted?

Defining the standard model of PA so that a space alien could understand

Simple fuzz pedal using breadboard

In general, would I need to season a meat when making a sauce?

Plot twist where the antagonist wins

What was the idiom for something that we take without a doubt?

Is real public IP Address hidden when using a system wide proxy in Windows 10?

Is neural networks training done one-by-one?

Which is the common name of Mind Flayers?

What is the object moving across the ceiling in this stock footage?

Why do Ryanair allow me to book connecting itineraries through a third party, but not through their own website?

Popcorn is the only acceptable snack to consume while watching a movie

Computing the matrix powers of a non-diagonalizable matrix

Why doesn't the Earth accelerate towards the Moon?

Cipher Block Chaining - How do you change the plaintext of all blocks?

Should breaking down something like a door be adjudicated as an attempt to beat its AC and HP, or as an ability check against a set DC?

How to respond to an upset student?

Should I disclose a colleague's illness (that I should not know) when others badmouth him

When and what was the first 3D acceleration device ever released?

Would jet fuel for an F-16 or F-35 be producible during WW2?



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

















  • 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

















  • 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














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













share|improve this question











share|improve this question




share|improve this question










asked May 13 at 17:09









SpeedOfRoundSpeedOfRound

1363




1363







  • 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
    );



    );













    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.6k1374118




        23.6k1374118



























            draft saved

            draft discarded
















































            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

            Wikipedia:Vital articles Мазмуну Biography - Өмүр баян Philosophy and psychology - Философия жана психология Religion - Дин Social sciences - Коомдук илимдер Language and literature - Тил жана адабият Science - Илим Technology - Технология Arts and recreation - Искусство жана эс алуу History and geography - Тарых жана география Навигация менюсу

            Bruxelas-Capital Índice Historia | Composición | Situación lingüística | Clima | Cidades irmandadas | Notas | Véxase tamén | Menú de navegacióneO uso das linguas en Bruxelas e a situación do neerlandés"Rexión de Bruxelas Capital"o orixinalSitio da rexiónPáxina de Bruselas no sitio da Oficina de Promoción Turística de Valonia e BruxelasMapa Interactivo da Rexión de Bruxelas-CapitaleeWorldCat332144929079854441105155190212ID28008674080552-90000 0001 0666 3698n94104302ID540940339365017018237

            What should I write in an apology letter, since I have decided not to join a company after accepting an offer letterShould I keep looking after accepting a job offer?What should I do when I've been verbally told I would get an offer letter, but still haven't gotten one after 4 weeks?Do I accept an offer from a company that I am not likely to join?New job hasn't confirmed starting date and I want to give current employer as much notice as possibleHow should I address my manager in my resignation letter?HR delayed background verification, now jobless as resignedNo email communication after accepting a formal written offer. How should I phrase the call?What should I do if after receiving a verbal offer letter I am informed that my written job offer is put on hold due to some internal issues?Should I inform the current employer that I am about to resign within 1-2 weeks since I have signed the offer letter and waiting for visa?What company will do, if I send their offer letter to another company