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

            Club Baloncesto Breogán Índice Historia | Pavillón | Nome | O Breogán na cultura popular | Xogadores | Adestradores | Presidentes | Palmarés | Historial | Líderes | Notas | Véxase tamén | Menú de navegacióncbbreogan.galCadroGuía oficial da ACB 2009-10, páxina 201Guía oficial ACB 1992, páxina 183. Editorial DB.É de 6.500 espectadores sentados axeitándose á última normativa"Estudiantes Junior, entre as mellores canteiras"o orixinalHemeroteca El Mundo Deportivo, 16 setembro de 1970, páxina 12Historia do BreogánAlfredo Pérez, o último canoneiroHistoria C.B. BreogánHemeroteca de El Mundo DeportivoJimmy Wright, norteamericano do Breogán deixará Lugo por ameazas de morteResultados de Breogán en 1986-87Resultados de Breogán en 1990-91Ficha de Velimir Perasović en acb.comResultados de Breogán en 1994-95Breogán arrasa al Barça. "El Mundo Deportivo", 27 de setembro de 1999, páxina 58CB Breogán - FC BarcelonaA FEB invita a participar nunha nova Liga EuropeaCharlie Bell na prensa estatalMáximos anotadores 2005Tempada 2005-06 : Tódolos Xogadores da Xornada""Non quero pensar nunha man negra, mais pregúntome que está a pasar""o orixinalRaúl López, orgulloso dos xogadores, presume da boa saúde económica do BreogánJulio González confirma que cesa como presidente del BreogánHomenaxe a Lisardo GómezA tempada do rexurdimento celesteEntrevista a Lisardo GómezEl COB dinamita el Pazo para forzar el quinto (69-73)Cafés Candelas, patrocinador del CB Breogán"Suso Lázare, novo presidente do Breogán"o orixinalCafés Candelas Breogán firma el mayor triunfo de la historiaEl Breogán realizará 17 homenajes por su cincuenta aniversario"O Breogán honra ao seu fundador e primeiro presidente"o orixinalMiguel Giao recibiu a homenaxe do PazoHomenaxe aos primeiros gladiadores celestesO home que nos amosa como ver o Breo co corazónTita Franco será homenaxeada polos #50anosdeBreoJulio Vila recibirá unha homenaxe in memoriam polos #50anosdeBreo"O Breogán homenaxeará aos seus aboados máis veteráns"Pechada ovación a «Capi» Sanmartín e Ricardo «Corazón de González»Homenaxe por décadas de informaciónPaco García volve ao Pazo con motivo do 50 aniversario"Resultados y clasificaciones""O Cafés Candelas Breogán, campión da Copa Princesa""O Cafés Candelas Breogán, equipo ACB"C.B. Breogán"Proxecto social"o orixinal"Centros asociados"o orixinalFicha en imdb.comMario Camus trata la recuperación del amor en 'La vieja música', su última película"Páxina web oficial""Club Baloncesto Breogán""C. B. Breogán S.A.D."eehttp://www.fegaba.com

            Vilaño, A Laracha Índice Patrimonio | Lugares e parroquias | Véxase tamén | Menú de navegación43°14′52″N 8°36′03″O / 43.24775, -8.60070

            Cegueira Índice Epidemioloxía | Deficiencia visual | Tipos de cegueira | Principais causas de cegueira | Tratamento | Técnicas de adaptación e axudas | Vida dos cegos | Primeiros auxilios | Crenzas respecto das persoas cegas | Crenzas das persoas cegas | O neno deficiente visual | Aspectos psicolóxicos da cegueira | Notas | Véxase tamén | Menú de navegación54.054.154.436928256blindnessDicionario da Real Academia GalegaPortal das Palabras"International Standards: Visual Standards — Aspects and Ranges of Vision Loss with Emphasis on Population Surveys.""Visual impairment and blindness""Presentan un plan para previr a cegueira"o orixinalACCDV Associació Catalana de Cecs i Disminuïts Visuals - PMFTrachoma"Effect of gene therapy on visual function in Leber's congenital amaurosis"1844137110.1056/NEJMoa0802268Cans guía - os mellores amigos dos cegosArquivadoEscola de cans guía para cegos en Mortágua, PortugalArquivado"Tecnología para ciegos y deficientes visuales. Recopilación de recursos gratuitos en la Red""Colorino""‘COL.diesis’, escuchar los sonidos del color""COL.diesis: Transforming Colour into Melody and Implementing the Result in a Colour Sensor Device"o orixinal"Sistema de desarrollo de sinestesia color-sonido para invidentes utilizando un protocolo de audio""Enseñanza táctil - geometría y color. Juegos didácticos para niños ciegos y videntes""Sistema Constanz"L'ocupació laboral dels cecs a l'Estat espanyol està pràcticament equiparada a la de les persones amb visió, entrevista amb Pedro ZuritaONCE (Organización Nacional de Cegos de España)Prevención da cegueiraDescrición de deficiencias visuais (Disc@pnet)Braillín, un boneco atractivo para calquera neno, con ou sen discapacidade, que permite familiarizarse co sistema de escritura e lectura brailleAxudas Técnicas36838ID00897494007150-90057129528256DOID:1432HP:0000618D001766C10.597.751.941.162C97109C0155020