Fine tuning MS SQL server query joining two tables with grouped result
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:
And here's the output I want:
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:
I know that its very close to the result I want, however its not exactly the same :(
sql sql-server join
add a comment |
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:
And here's the output I want:
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:
I know that its very close to the result I want, however its not exactly the same :(
sql sql-server join
Matbailie, Thanks! I missed that one.
– mctl87
Nov 18 '18 at 10:23
add a comment |
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:
And here's the output I want:
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:
I know that its very close to the result I want, however its not exactly the same :(
sql sql-server join
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:
And here's the output I want:
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:
I know that its very close to the result I want, however its not exactly the same :(
sql sql-server join
sql sql-server join
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
add a comment |
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
add a comment |
2 Answers
2
active
oldest
votes
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
Not only it works, but it works in a second ! Thank you ! :)
– mctl87
Nov 18 '18 at 10:40
add a comment |
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..!! :)
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
Not only it works, but it works in a second ! Thank you ! :)
– mctl87
Nov 18 '18 at 10:40
add a comment |
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
Not only it works, but it works in a second ! Thank you ! :)
– mctl87
Nov 18 '18 at 10:40
add a comment |
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
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
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
add a comment |
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
add a comment |
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..!! :)
add a comment |
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..!! :)
add a comment |
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..!! :)
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..!! :)
answered Nov 19 '18 at 6:32
nandakumar_rnandakumar_r
11
11
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
Matbailie, Thanks! I missed that one.
– mctl87
Nov 18 '18 at 10:23