Fine tuning MS SQL server query joining two tables with grouped result












2















I would like to ask you if there's efficient way to write a query to retrieve the data from tables provided below and display only the columns and values I want. I already wrote two queries however the first one is a bit slow and in the second I got more columns than I want.



So here are my three tables:



enter image description here



enter image description here



enter image description here



And here's the output I want:
enter image description here



Output table should display monthly values from Jan till Dec.
In the real database Table A has ~40k rows, Table B has 20 rows and Table C has ~1 million rows.
Below you can see part of a query which I wrote and which generate desired output, however when I ran it for real DB it takes ~20-30 seconds:



  SELECT TableA.Id
,TableA.Title
,TableA.Description
,TableB.Title
,f1.[Value] as TableC_JanuaryValue
,f2.[Value] as TableC_FebruaryValue
....
FROM <tablename>
INNER JOIN TableB ON TableB.Id = TableA.TableB_FK_Id
INNER JOIN TableC as f1 ON (f1.TableA_FK_Id = TableA.Id AND f1.[Year] = 2018 AND f1.[Month] = 1)
INNER JOIN TableC as f2 ON (f2.TableA_FK_Id = TableA.Id AND f2.[Year] = 2018 AND f2.[Month] = 2)
.....


I was trying to write it differently and make it faster and I managed to get it down to 2-3 seconds, however the output is not exactly what I want.
Here's the second query:



  SELECT TableA.Id
,TableA.Title
,TableA.Description
,TableB.Title
,count(case when TableC.Value = 'V1' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV1
,count(case when TableC.Value = 'V2' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV2
,count(case when TableC.Value = 'V3' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV3
,count(case when TableC.Value = 'V1' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV1
,count(case when TableC.Value = 'V2' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV2
,count(case when TableC.Value = 'V3' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV3
....
FROM <tablename>
INNER JOIN TableB ON TableB.Id = TableA.TableB_FK_Id
INNER JOIN TableC ON TableA.Id = TableC.TAbleA_FK_Id
where TableC.[Year] = 2018
group by TableA.Id, TableA.Title, TableA.Description, TableB.Title


And here's what I get:
enter image description here



I know that its very close to the result I want, however its not exactly the same :(










share|improve this question

























  • Matbailie, Thanks! I missed that one.

    – mctl87
    Nov 18 '18 at 10:23
















2















I would like to ask you if there's efficient way to write a query to retrieve the data from tables provided below and display only the columns and values I want. I already wrote two queries however the first one is a bit slow and in the second I got more columns than I want.



So here are my three tables:



enter image description here



enter image description here



enter image description here



And here's the output I want:
enter image description here



Output table should display monthly values from Jan till Dec.
In the real database Table A has ~40k rows, Table B has 20 rows and Table C has ~1 million rows.
Below you can see part of a query which I wrote and which generate desired output, however when I ran it for real DB it takes ~20-30 seconds:



  SELECT TableA.Id
,TableA.Title
,TableA.Description
,TableB.Title
,f1.[Value] as TableC_JanuaryValue
,f2.[Value] as TableC_FebruaryValue
....
FROM <tablename>
INNER JOIN TableB ON TableB.Id = TableA.TableB_FK_Id
INNER JOIN TableC as f1 ON (f1.TableA_FK_Id = TableA.Id AND f1.[Year] = 2018 AND f1.[Month] = 1)
INNER JOIN TableC as f2 ON (f2.TableA_FK_Id = TableA.Id AND f2.[Year] = 2018 AND f2.[Month] = 2)
.....


I was trying to write it differently and make it faster and I managed to get it down to 2-3 seconds, however the output is not exactly what I want.
Here's the second query:



  SELECT TableA.Id
,TableA.Title
,TableA.Description
,TableB.Title
,count(case when TableC.Value = 'V1' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV1
,count(case when TableC.Value = 'V2' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV2
,count(case when TableC.Value = 'V3' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV3
,count(case when TableC.Value = 'V1' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV1
,count(case when TableC.Value = 'V2' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV2
,count(case when TableC.Value = 'V3' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV3
....
FROM <tablename>
INNER JOIN TableB ON TableB.Id = TableA.TableB_FK_Id
INNER JOIN TableC ON TableA.Id = TableC.TAbleA_FK_Id
where TableC.[Year] = 2018
group by TableA.Id, TableA.Title, TableA.Description, TableB.Title


And here's what I get:
enter image description here



I know that its very close to the result I want, however its not exactly the same :(










share|improve this question

























  • Matbailie, Thanks! I missed that one.

    – mctl87
    Nov 18 '18 at 10:23














2












2








2








I would like to ask you if there's efficient way to write a query to retrieve the data from tables provided below and display only the columns and values I want. I already wrote two queries however the first one is a bit slow and in the second I got more columns than I want.



So here are my three tables:



enter image description here



enter image description here



enter image description here



And here's the output I want:
enter image description here



Output table should display monthly values from Jan till Dec.
In the real database Table A has ~40k rows, Table B has 20 rows and Table C has ~1 million rows.
Below you can see part of a query which I wrote and which generate desired output, however when I ran it for real DB it takes ~20-30 seconds:



  SELECT TableA.Id
,TableA.Title
,TableA.Description
,TableB.Title
,f1.[Value] as TableC_JanuaryValue
,f2.[Value] as TableC_FebruaryValue
....
FROM <tablename>
INNER JOIN TableB ON TableB.Id = TableA.TableB_FK_Id
INNER JOIN TableC as f1 ON (f1.TableA_FK_Id = TableA.Id AND f1.[Year] = 2018 AND f1.[Month] = 1)
INNER JOIN TableC as f2 ON (f2.TableA_FK_Id = TableA.Id AND f2.[Year] = 2018 AND f2.[Month] = 2)
.....


I was trying to write it differently and make it faster and I managed to get it down to 2-3 seconds, however the output is not exactly what I want.
Here's the second query:



  SELECT TableA.Id
,TableA.Title
,TableA.Description
,TableB.Title
,count(case when TableC.Value = 'V1' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV1
,count(case when TableC.Value = 'V2' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV2
,count(case when TableC.Value = 'V3' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV3
,count(case when TableC.Value = 'V1' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV1
,count(case when TableC.Value = 'V2' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV2
,count(case when TableC.Value = 'V3' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV3
....
FROM <tablename>
INNER JOIN TableB ON TableB.Id = TableA.TableB_FK_Id
INNER JOIN TableC ON TableA.Id = TableC.TAbleA_FK_Id
where TableC.[Year] = 2018
group by TableA.Id, TableA.Title, TableA.Description, TableB.Title


And here's what I get:
enter image description here



I know that its very close to the result I want, however its not exactly the same :(










share|improve this question
















I would like to ask you if there's efficient way to write a query to retrieve the data from tables provided below and display only the columns and values I want. I already wrote two queries however the first one is a bit slow and in the second I got more columns than I want.



So here are my three tables:



enter image description here



enter image description here



enter image description here



And here's the output I want:
enter image description here



Output table should display monthly values from Jan till Dec.
In the real database Table A has ~40k rows, Table B has 20 rows and Table C has ~1 million rows.
Below you can see part of a query which I wrote and which generate desired output, however when I ran it for real DB it takes ~20-30 seconds:



  SELECT TableA.Id
,TableA.Title
,TableA.Description
,TableB.Title
,f1.[Value] as TableC_JanuaryValue
,f2.[Value] as TableC_FebruaryValue
....
FROM <tablename>
INNER JOIN TableB ON TableB.Id = TableA.TableB_FK_Id
INNER JOIN TableC as f1 ON (f1.TableA_FK_Id = TableA.Id AND f1.[Year] = 2018 AND f1.[Month] = 1)
INNER JOIN TableC as f2 ON (f2.TableA_FK_Id = TableA.Id AND f2.[Year] = 2018 AND f2.[Month] = 2)
.....


I was trying to write it differently and make it faster and I managed to get it down to 2-3 seconds, however the output is not exactly what I want.
Here's the second query:



  SELECT TableA.Id
,TableA.Title
,TableA.Description
,TableB.Title
,count(case when TableC.Value = 'V1' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV1
,count(case when TableC.Value = 'V2' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV2
,count(case when TableC.Value = 'V3' and TableC.[Month] = 1 then TableC.Id end) as JAN_IsV3
,count(case when TableC.Value = 'V1' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV1
,count(case when TableC.Value = 'V2' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV2
,count(case when TableC.Value = 'V3' and TableC.[Month] = 2 then TableC.Id end) as FEB_IsV3
....
FROM <tablename>
INNER JOIN TableB ON TableB.Id = TableA.TableB_FK_Id
INNER JOIN TableC ON TableA.Id = TableC.TAbleA_FK_Id
where TableC.[Year] = 2018
group by TableA.Id, TableA.Title, TableA.Description, TableB.Title


And here's what I get:
enter image description here



I know that its very close to the result I want, however its not exactly the same :(







sql sql-server join






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 18 '18 at 10:23







mctl87

















asked Nov 18 '18 at 10:08









mctl87mctl87

12239




12239













  • Matbailie, Thanks! I missed that one.

    – mctl87
    Nov 18 '18 at 10:23



















  • Matbailie, Thanks! I missed that one.

    – mctl87
    Nov 18 '18 at 10:23

















Matbailie, Thanks! I missed that one.

– mctl87
Nov 18 '18 at 10:23





Matbailie, Thanks! I missed that one.

– mctl87
Nov 18 '18 at 10:23












2 Answers
2






active

oldest

votes


















2














Just do the pivoting on TableC before you join it to the others. And use MAX(CASE) instead of COUNT(CASE)



SELECT
TableA.Id
,TableA.Title
,TableA.Description
,TableB.Title
,TableC.*
FROM
TableA
INNER JOIN
TableB
ON TableB.Id = TableA.TableB_FK_Id
INNER JOIN
(
SELECT
TableA_FK_Id,
MAX(CASE WHEN [Month] = 1 THEN Value END) AS JAN,
MAX(CASE WHEN [Month] = 2 THEN Value END) AS FEB,
MAX(CASE WHEN [Month] = 3 THEN Value END) AS MAR,
...
FROM
TableC
WHERE
[YEAR] = 2018
GROUP BY
TableA_FK_Id
)
TableC
ON TableA.Id = TableC.TableA_FK_Id





share|improve this answer


























  • Not only it works, but it works in a second ! Thank you ! :)

    – mctl87
    Nov 18 '18 at 10:40



















-1














 SELECT 
tablea.Id AS TableA_Id,
tablea.Title AS TableA_Title,
tablea.Description AS TableA_Description,
(SELECT tableb.Title FROM tableb WHERE tableb.Id = TableA.TableB_FK_Id) AS TableB_Id,
(SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 1) AS TableC_JanValue,
(SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 2) AS TableC_FebValue
FROM tablea;


this one also u can try..!! :)






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    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: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    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%2fstackoverflow.com%2fquestions%2f53359731%2ffine-tuning-ms-sql-server-query-joining-two-tables-with-grouped-result%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    Just do the pivoting on TableC before you join it to the others. And use MAX(CASE) instead of COUNT(CASE)



    SELECT
    TableA.Id
    ,TableA.Title
    ,TableA.Description
    ,TableB.Title
    ,TableC.*
    FROM
    TableA
    INNER JOIN
    TableB
    ON TableB.Id = TableA.TableB_FK_Id
    INNER JOIN
    (
    SELECT
    TableA_FK_Id,
    MAX(CASE WHEN [Month] = 1 THEN Value END) AS JAN,
    MAX(CASE WHEN [Month] = 2 THEN Value END) AS FEB,
    MAX(CASE WHEN [Month] = 3 THEN Value END) AS MAR,
    ...
    FROM
    TableC
    WHERE
    [YEAR] = 2018
    GROUP BY
    TableA_FK_Id
    )
    TableC
    ON TableA.Id = TableC.TableA_FK_Id





    share|improve this answer


























    • Not only it works, but it works in a second ! Thank you ! :)

      – mctl87
      Nov 18 '18 at 10:40
















    2














    Just do the pivoting on TableC before you join it to the others. And use MAX(CASE) instead of COUNT(CASE)



    SELECT
    TableA.Id
    ,TableA.Title
    ,TableA.Description
    ,TableB.Title
    ,TableC.*
    FROM
    TableA
    INNER JOIN
    TableB
    ON TableB.Id = TableA.TableB_FK_Id
    INNER JOIN
    (
    SELECT
    TableA_FK_Id,
    MAX(CASE WHEN [Month] = 1 THEN Value END) AS JAN,
    MAX(CASE WHEN [Month] = 2 THEN Value END) AS FEB,
    MAX(CASE WHEN [Month] = 3 THEN Value END) AS MAR,
    ...
    FROM
    TableC
    WHERE
    [YEAR] = 2018
    GROUP BY
    TableA_FK_Id
    )
    TableC
    ON TableA.Id = TableC.TableA_FK_Id





    share|improve this answer


























    • Not only it works, but it works in a second ! Thank you ! :)

      – mctl87
      Nov 18 '18 at 10:40














    2












    2








    2







    Just do the pivoting on TableC before you join it to the others. And use MAX(CASE) instead of COUNT(CASE)



    SELECT
    TableA.Id
    ,TableA.Title
    ,TableA.Description
    ,TableB.Title
    ,TableC.*
    FROM
    TableA
    INNER JOIN
    TableB
    ON TableB.Id = TableA.TableB_FK_Id
    INNER JOIN
    (
    SELECT
    TableA_FK_Id,
    MAX(CASE WHEN [Month] = 1 THEN Value END) AS JAN,
    MAX(CASE WHEN [Month] = 2 THEN Value END) AS FEB,
    MAX(CASE WHEN [Month] = 3 THEN Value END) AS MAR,
    ...
    FROM
    TableC
    WHERE
    [YEAR] = 2018
    GROUP BY
    TableA_FK_Id
    )
    TableC
    ON TableA.Id = TableC.TableA_FK_Id





    share|improve this answer















    Just do the pivoting on TableC before you join it to the others. And use MAX(CASE) instead of COUNT(CASE)



    SELECT
    TableA.Id
    ,TableA.Title
    ,TableA.Description
    ,TableB.Title
    ,TableC.*
    FROM
    TableA
    INNER JOIN
    TableB
    ON TableB.Id = TableA.TableB_FK_Id
    INNER JOIN
    (
    SELECT
    TableA_FK_Id,
    MAX(CASE WHEN [Month] = 1 THEN Value END) AS JAN,
    MAX(CASE WHEN [Month] = 2 THEN Value END) AS FEB,
    MAX(CASE WHEN [Month] = 3 THEN Value END) AS MAR,
    ...
    FROM
    TableC
    WHERE
    [YEAR] = 2018
    GROUP BY
    TableA_FK_Id
    )
    TableC
    ON TableA.Id = TableC.TableA_FK_Id






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 18 '18 at 10:30

























    answered Nov 18 '18 at 10:20









    MatBailieMatBailie

    59.4k1475110




    59.4k1475110













    • Not only it works, but it works in a second ! Thank you ! :)

      – mctl87
      Nov 18 '18 at 10:40



















    • Not only it works, but it works in a second ! Thank you ! :)

      – mctl87
      Nov 18 '18 at 10:40

















    Not only it works, but it works in a second ! Thank you ! :)

    – mctl87
    Nov 18 '18 at 10:40





    Not only it works, but it works in a second ! Thank you ! :)

    – mctl87
    Nov 18 '18 at 10:40













    -1














     SELECT 
    tablea.Id AS TableA_Id,
    tablea.Title AS TableA_Title,
    tablea.Description AS TableA_Description,
    (SELECT tableb.Title FROM tableb WHERE tableb.Id = TableA.TableB_FK_Id) AS TableB_Id,
    (SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 1) AS TableC_JanValue,
    (SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 2) AS TableC_FebValue
    FROM tablea;


    this one also u can try..!! :)






    share|improve this answer




























      -1














       SELECT 
      tablea.Id AS TableA_Id,
      tablea.Title AS TableA_Title,
      tablea.Description AS TableA_Description,
      (SELECT tableb.Title FROM tableb WHERE tableb.Id = TableA.TableB_FK_Id) AS TableB_Id,
      (SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 1) AS TableC_JanValue,
      (SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 2) AS TableC_FebValue
      FROM tablea;


      this one also u can try..!! :)






      share|improve this answer


























        -1












        -1








        -1







         SELECT 
        tablea.Id AS TableA_Id,
        tablea.Title AS TableA_Title,
        tablea.Description AS TableA_Description,
        (SELECT tableb.Title FROM tableb WHERE tableb.Id = TableA.TableB_FK_Id) AS TableB_Id,
        (SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 1) AS TableC_JanValue,
        (SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 2) AS TableC_FebValue
        FROM tablea;


        this one also u can try..!! :)






        share|improve this answer













         SELECT 
        tablea.Id AS TableA_Id,
        tablea.Title AS TableA_Title,
        tablea.Description AS TableA_Description,
        (SELECT tableb.Title FROM tableb WHERE tableb.Id = TableA.TableB_FK_Id) AS TableB_Id,
        (SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 1) AS TableC_JanValue,
        (SELECT tablec.Value FROM tablec WHERE tablea.Id = TableC.TableA_FK_Id AND tablec.Month = 2) AS TableC_FebValue
        FROM tablea;


        this one also u can try..!! :)







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 19 '18 at 6:32









        nandakumar_rnandakumar_r

        11




        11






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • 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%2fstackoverflow.com%2fquestions%2f53359731%2ffine-tuning-ms-sql-server-query-joining-two-tables-with-grouped-result%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







            這個網誌中的熱門文章

            Tangent Lines Diagram Along Smooth Curve

            Yusuf al-Mu'taman ibn Hud

            Zucchini