Query to show each sites stock transfer history between all other sites
The below query is used to return a dataset for a SSRS report. It works fine and is quick enough but I am looking for any improvements that could be made.
The client has asked to see all transfers between sites and the report should look like:
Site1
- Site 2
- Site 3
Site2
- Site 1
- Site 3
Each row should also show the value of the transfer to that site and from that site. Duplicated data is expected I.E If Site 1 transferred goods to Site 2 then Site 2 should display the same value in the from column. If no transfer takes place the site should be visible but with a value of 0 in both To and from columns.
The Exists clause must remain as well as it is used to workout descendants of selected site.
WITH Transfers_CTE(FromSiteNo
,ToSiteNo
,Value)
AS (
SELECT Transfers.FromSiteNo
,Transfers.ToSiteNo
,SUM(Transfers.[Value]) AS Value
FROM dbo.Transfers
WHERE Transfers.MoveDate BETWEEN @SessionDateFrom AND @SessionDateTo
GROUP BY Transfers.FromSiteNo
,Transfers.ToSiteNo)
SELECT CS.No AS SiteNo
,CS.Name AS SiteName
,JoinedSites.No AS OtherSiteNo
,JoinedSites.Name AS OtherSiteName
,ISNULL(ToTable.[Value],0) AS ToValue
,ISNULL(FromTable.[Value],0) AS FromValue
FROM dbo.CfgSites AS CS
FULL OUTER JOIN dbo.CfgSites AS JoinedSites ON CS.No != JoinedSites.No
LEFT JOIN Transfers_CTE AS ToTable ON ToTable.FromSiteNo = CS.No
AND ToTable.ToSiteNo = JoinedSites.No
LEFT JOIN Transfers_CTE AS FromTable ON FromTable.ToSiteNo = CS.No
AND FromTable.FromSiteNo = JoinedSites.No
WHERE EXISTS
(
SELECT DescendantSites.Descendant
FROM dbo.DescendantSites
WHERE DescendantSites.Parent IN(@SiteNo)
AND DescendantSites.Descendant = CS.No
)
ORDER BY CS.No;
Subset DDL for CfgSites and Transfer View that only includes required fields
/****** Object: Table [dbo].[CfgSites] Script Date: 13/04/2018 08:47:32 ******/
CREATE TABLE [dbo].[CfgSites](
[No] [smallint] NOT NULL,
[Name] [varchar](50) NULL)
GO
/****** Object: View [dbo].[Transfers] Script Date: 13/04/2018 08:47:32 ******/
CREATE VIEW [dbo].[Transfers]
AS
SELECT [SiteNo] AS FromSiteNo
,[Site2No] AS ToSiteNo
,[Date] AS MoveDate
,[Value]
FROM PluMovement
WHERE MoveType = 4
AND Processed = 1
sql sql-server t-sql
add a comment |
The below query is used to return a dataset for a SSRS report. It works fine and is quick enough but I am looking for any improvements that could be made.
The client has asked to see all transfers between sites and the report should look like:
Site1
- Site 2
- Site 3
Site2
- Site 1
- Site 3
Each row should also show the value of the transfer to that site and from that site. Duplicated data is expected I.E If Site 1 transferred goods to Site 2 then Site 2 should display the same value in the from column. If no transfer takes place the site should be visible but with a value of 0 in both To and from columns.
The Exists clause must remain as well as it is used to workout descendants of selected site.
WITH Transfers_CTE(FromSiteNo
,ToSiteNo
,Value)
AS (
SELECT Transfers.FromSiteNo
,Transfers.ToSiteNo
,SUM(Transfers.[Value]) AS Value
FROM dbo.Transfers
WHERE Transfers.MoveDate BETWEEN @SessionDateFrom AND @SessionDateTo
GROUP BY Transfers.FromSiteNo
,Transfers.ToSiteNo)
SELECT CS.No AS SiteNo
,CS.Name AS SiteName
,JoinedSites.No AS OtherSiteNo
,JoinedSites.Name AS OtherSiteName
,ISNULL(ToTable.[Value],0) AS ToValue
,ISNULL(FromTable.[Value],0) AS FromValue
FROM dbo.CfgSites AS CS
FULL OUTER JOIN dbo.CfgSites AS JoinedSites ON CS.No != JoinedSites.No
LEFT JOIN Transfers_CTE AS ToTable ON ToTable.FromSiteNo = CS.No
AND ToTable.ToSiteNo = JoinedSites.No
LEFT JOIN Transfers_CTE AS FromTable ON FromTable.ToSiteNo = CS.No
AND FromTable.FromSiteNo = JoinedSites.No
WHERE EXISTS
(
SELECT DescendantSites.Descendant
FROM dbo.DescendantSites
WHERE DescendantSites.Parent IN(@SiteNo)
AND DescendantSites.Descendant = CS.No
)
ORDER BY CS.No;
Subset DDL for CfgSites and Transfer View that only includes required fields
/****** Object: Table [dbo].[CfgSites] Script Date: 13/04/2018 08:47:32 ******/
CREATE TABLE [dbo].[CfgSites](
[No] [smallint] NOT NULL,
[Name] [varchar](50) NULL)
GO
/****** Object: View [dbo].[Transfers] Script Date: 13/04/2018 08:47:32 ******/
CREATE VIEW [dbo].[Transfers]
AS
SELECT [SiteNo] AS FromSiteNo
,[Site2No] AS ToSiteNo
,[Date] AS MoveDate
,[Value]
FROM PluMovement
WHERE MoveType = 4
AND Processed = 1
sql sql-server t-sql
Can you elaborate on this part:WHERE DescendantSites.Parent IN(@SiteNo)
I'm assuming this is a delimited list? If not, you can simply use=
– scsimon
Apr 12 '18 at 13:23
@scsimon the parameter SiteNo can be multiple values or just a single entry. It allows the customer to view any selected sites they want.
– NinjaArekku
Apr 12 '18 at 13:52
add a comment |
The below query is used to return a dataset for a SSRS report. It works fine and is quick enough but I am looking for any improvements that could be made.
The client has asked to see all transfers between sites and the report should look like:
Site1
- Site 2
- Site 3
Site2
- Site 1
- Site 3
Each row should also show the value of the transfer to that site and from that site. Duplicated data is expected I.E If Site 1 transferred goods to Site 2 then Site 2 should display the same value in the from column. If no transfer takes place the site should be visible but with a value of 0 in both To and from columns.
The Exists clause must remain as well as it is used to workout descendants of selected site.
WITH Transfers_CTE(FromSiteNo
,ToSiteNo
,Value)
AS (
SELECT Transfers.FromSiteNo
,Transfers.ToSiteNo
,SUM(Transfers.[Value]) AS Value
FROM dbo.Transfers
WHERE Transfers.MoveDate BETWEEN @SessionDateFrom AND @SessionDateTo
GROUP BY Transfers.FromSiteNo
,Transfers.ToSiteNo)
SELECT CS.No AS SiteNo
,CS.Name AS SiteName
,JoinedSites.No AS OtherSiteNo
,JoinedSites.Name AS OtherSiteName
,ISNULL(ToTable.[Value],0) AS ToValue
,ISNULL(FromTable.[Value],0) AS FromValue
FROM dbo.CfgSites AS CS
FULL OUTER JOIN dbo.CfgSites AS JoinedSites ON CS.No != JoinedSites.No
LEFT JOIN Transfers_CTE AS ToTable ON ToTable.FromSiteNo = CS.No
AND ToTable.ToSiteNo = JoinedSites.No
LEFT JOIN Transfers_CTE AS FromTable ON FromTable.ToSiteNo = CS.No
AND FromTable.FromSiteNo = JoinedSites.No
WHERE EXISTS
(
SELECT DescendantSites.Descendant
FROM dbo.DescendantSites
WHERE DescendantSites.Parent IN(@SiteNo)
AND DescendantSites.Descendant = CS.No
)
ORDER BY CS.No;
Subset DDL for CfgSites and Transfer View that only includes required fields
/****** Object: Table [dbo].[CfgSites] Script Date: 13/04/2018 08:47:32 ******/
CREATE TABLE [dbo].[CfgSites](
[No] [smallint] NOT NULL,
[Name] [varchar](50) NULL)
GO
/****** Object: View [dbo].[Transfers] Script Date: 13/04/2018 08:47:32 ******/
CREATE VIEW [dbo].[Transfers]
AS
SELECT [SiteNo] AS FromSiteNo
,[Site2No] AS ToSiteNo
,[Date] AS MoveDate
,[Value]
FROM PluMovement
WHERE MoveType = 4
AND Processed = 1
sql sql-server t-sql
The below query is used to return a dataset for a SSRS report. It works fine and is quick enough but I am looking for any improvements that could be made.
The client has asked to see all transfers between sites and the report should look like:
Site1
- Site 2
- Site 3
Site2
- Site 1
- Site 3
Each row should also show the value of the transfer to that site and from that site. Duplicated data is expected I.E If Site 1 transferred goods to Site 2 then Site 2 should display the same value in the from column. If no transfer takes place the site should be visible but with a value of 0 in both To and from columns.
The Exists clause must remain as well as it is used to workout descendants of selected site.
WITH Transfers_CTE(FromSiteNo
,ToSiteNo
,Value)
AS (
SELECT Transfers.FromSiteNo
,Transfers.ToSiteNo
,SUM(Transfers.[Value]) AS Value
FROM dbo.Transfers
WHERE Transfers.MoveDate BETWEEN @SessionDateFrom AND @SessionDateTo
GROUP BY Transfers.FromSiteNo
,Transfers.ToSiteNo)
SELECT CS.No AS SiteNo
,CS.Name AS SiteName
,JoinedSites.No AS OtherSiteNo
,JoinedSites.Name AS OtherSiteName
,ISNULL(ToTable.[Value],0) AS ToValue
,ISNULL(FromTable.[Value],0) AS FromValue
FROM dbo.CfgSites AS CS
FULL OUTER JOIN dbo.CfgSites AS JoinedSites ON CS.No != JoinedSites.No
LEFT JOIN Transfers_CTE AS ToTable ON ToTable.FromSiteNo = CS.No
AND ToTable.ToSiteNo = JoinedSites.No
LEFT JOIN Transfers_CTE AS FromTable ON FromTable.ToSiteNo = CS.No
AND FromTable.FromSiteNo = JoinedSites.No
WHERE EXISTS
(
SELECT DescendantSites.Descendant
FROM dbo.DescendantSites
WHERE DescendantSites.Parent IN(@SiteNo)
AND DescendantSites.Descendant = CS.No
)
ORDER BY CS.No;
Subset DDL for CfgSites and Transfer View that only includes required fields
/****** Object: Table [dbo].[CfgSites] Script Date: 13/04/2018 08:47:32 ******/
CREATE TABLE [dbo].[CfgSites](
[No] [smallint] NOT NULL,
[Name] [varchar](50) NULL)
GO
/****** Object: View [dbo].[Transfers] Script Date: 13/04/2018 08:47:32 ******/
CREATE VIEW [dbo].[Transfers]
AS
SELECT [SiteNo] AS FromSiteNo
,[Site2No] AS ToSiteNo
,[Date] AS MoveDate
,[Value]
FROM PluMovement
WHERE MoveType = 4
AND Processed = 1
sql sql-server t-sql
sql sql-server t-sql
edited Apr 13 '18 at 8:24
NinjaArekku
asked Apr 12 '18 at 11:46
NinjaArekkuNinjaArekku
1126
1126
Can you elaborate on this part:WHERE DescendantSites.Parent IN(@SiteNo)
I'm assuming this is a delimited list? If not, you can simply use=
– scsimon
Apr 12 '18 at 13:23
@scsimon the parameter SiteNo can be multiple values or just a single entry. It allows the customer to view any selected sites they want.
– NinjaArekku
Apr 12 '18 at 13:52
add a comment |
Can you elaborate on this part:WHERE DescendantSites.Parent IN(@SiteNo)
I'm assuming this is a delimited list? If not, you can simply use=
– scsimon
Apr 12 '18 at 13:23
@scsimon the parameter SiteNo can be multiple values or just a single entry. It allows the customer to view any selected sites they want.
– NinjaArekku
Apr 12 '18 at 13:52
Can you elaborate on this part:
WHERE DescendantSites.Parent IN(@SiteNo)
I'm assuming this is a delimited list? If not, you can simply use =
– scsimon
Apr 12 '18 at 13:23
Can you elaborate on this part:
WHERE DescendantSites.Parent IN(@SiteNo)
I'm assuming this is a delimited list? If not, you can simply use =
– scsimon
Apr 12 '18 at 13:23
@scsimon the parameter SiteNo can be multiple values or just a single entry. It allows the customer to view any selected sites they want.
– NinjaArekku
Apr 12 '18 at 13:52
@scsimon the parameter SiteNo can be multiple values or just a single entry. It allows the customer to view any selected sites they want.
– NinjaArekku
Apr 12 '18 at 13:52
add a comment |
1 Answer
1
active
oldest
votes
Here is an attempt at a rewrite, but you didn't provide any DDL or DML so there is no way for me to test it. I'll list reasons for the changes below.
WITH Transfers_CTE (FromSiteNo, ToSiteNo, Value) AS
(
SELECT Transfers.FromSiteNo,
Transfers.ToSiteNo,
SUM( Transfers.Value ) AS Value
FROM dbo.Transfers
WHERE Transfers.MoveDate BETWEEN @SessionDateFrom AND @SessionDateTo
AND FromSiteNo <> ToSiteNo
GROUP BY Transfers.FromSiteNo,
Transfers.ToSiteNo
)
SELECT FromCS.No AS SiteNo,
FromCS.Name AS SiteName,
ToCS.No AS OtherSiteNo,
ToCS.Name AS OtherSiteName,
ISNULL( Transfers.Value, 0 ) AS ToFromValue
FROM dbo.CfgSites AS FromCS
LEFT JOIN Transfers_CTE AS Transfers
ON FromCS.No = Transfers.FromSiteNo
LEFT JOIN dbo.CfgSites AS ToCS
ON Transfers.ToSiteNo = ToCS.No
WHERE EXISTS
( SELECT DescendantSites.Descendant
FROM dbo.DescendantSites
WHERE DescendantSites.Parent IN ( @SiteNo )
AND DescendantSites.Descendant = FromCS.No)
ORDER BY FromCS.No
;
- Since
Cs.No
andJoinedSites.No
should not be equal, and they are joined to the From & To values of the CTE, I added the filter in the CTE to exclude any transfers where the To and From site matched. - Your Full Outer Join was effectively a left outer join because any results from the Right side table would have been excluded by the Left side reference of your EXISTS clause.
- You attempt to join transfers to sites from both directions. However, if A = B, then B = A. So if we get all of the
FromSite
joins established to CS on the first pass, there is no reason to do a second pass by joiningJoinedSites
to theFromSite
as they will already have found a match. This change also eliminates the near Cartesian product of joiningCfgSites
to itself. - If we consider the CS table our anchor, understanding it has all of the From Sites included, our problem then becomes how to get the To sites. The relationship between From and To is contained in the Transfers_CTE. Thus we just need to join back to the
CfgSites
using theToSiteNo
field to find the site information. - The Sum aggregate was at the grain of the Transfer relationship, To & From. This is maintained in the changes, but now there is only one value column, returning the Value that was transferred between From and To.
There is no need to join CfgSites
to itself directly, unless you may also need to show any ToFrom combinations that did not get any transfers.
Hopefully this will return your expected results. If not, provide some DDL/DML and I may take another look at it.
Thanks for the feedback. I realised that I haven't been clear enough in the purpose of the script so i have updated my question with, hopefully, a better reflection on what it has to achieve and included the DDL. In relation to point 1, is it worth adding a filter to an event that will only occur 0.01% of the time (through fault)? Would it impact performance if filtering for something it cant find?
– NinjaArekku
Apr 13 '18 at 8:06
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
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: "196"
};
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
});
}
});
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%2fcodereview.stackexchange.com%2fquestions%2f191864%2fquery-to-show-each-sites-stock-transfer-history-between-all-other-sites%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
Here is an attempt at a rewrite, but you didn't provide any DDL or DML so there is no way for me to test it. I'll list reasons for the changes below.
WITH Transfers_CTE (FromSiteNo, ToSiteNo, Value) AS
(
SELECT Transfers.FromSiteNo,
Transfers.ToSiteNo,
SUM( Transfers.Value ) AS Value
FROM dbo.Transfers
WHERE Transfers.MoveDate BETWEEN @SessionDateFrom AND @SessionDateTo
AND FromSiteNo <> ToSiteNo
GROUP BY Transfers.FromSiteNo,
Transfers.ToSiteNo
)
SELECT FromCS.No AS SiteNo,
FromCS.Name AS SiteName,
ToCS.No AS OtherSiteNo,
ToCS.Name AS OtherSiteName,
ISNULL( Transfers.Value, 0 ) AS ToFromValue
FROM dbo.CfgSites AS FromCS
LEFT JOIN Transfers_CTE AS Transfers
ON FromCS.No = Transfers.FromSiteNo
LEFT JOIN dbo.CfgSites AS ToCS
ON Transfers.ToSiteNo = ToCS.No
WHERE EXISTS
( SELECT DescendantSites.Descendant
FROM dbo.DescendantSites
WHERE DescendantSites.Parent IN ( @SiteNo )
AND DescendantSites.Descendant = FromCS.No)
ORDER BY FromCS.No
;
- Since
Cs.No
andJoinedSites.No
should not be equal, and they are joined to the From & To values of the CTE, I added the filter in the CTE to exclude any transfers where the To and From site matched. - Your Full Outer Join was effectively a left outer join because any results from the Right side table would have been excluded by the Left side reference of your EXISTS clause.
- You attempt to join transfers to sites from both directions. However, if A = B, then B = A. So if we get all of the
FromSite
joins established to CS on the first pass, there is no reason to do a second pass by joiningJoinedSites
to theFromSite
as they will already have found a match. This change also eliminates the near Cartesian product of joiningCfgSites
to itself. - If we consider the CS table our anchor, understanding it has all of the From Sites included, our problem then becomes how to get the To sites. The relationship between From and To is contained in the Transfers_CTE. Thus we just need to join back to the
CfgSites
using theToSiteNo
field to find the site information. - The Sum aggregate was at the grain of the Transfer relationship, To & From. This is maintained in the changes, but now there is only one value column, returning the Value that was transferred between From and To.
There is no need to join CfgSites
to itself directly, unless you may also need to show any ToFrom combinations that did not get any transfers.
Hopefully this will return your expected results. If not, provide some DDL/DML and I may take another look at it.
Thanks for the feedback. I realised that I haven't been clear enough in the purpose of the script so i have updated my question with, hopefully, a better reflection on what it has to achieve and included the DDL. In relation to point 1, is it worth adding a filter to an event that will only occur 0.01% of the time (through fault)? Would it impact performance if filtering for something it cant find?
– NinjaArekku
Apr 13 '18 at 8:06
add a comment |
Here is an attempt at a rewrite, but you didn't provide any DDL or DML so there is no way for me to test it. I'll list reasons for the changes below.
WITH Transfers_CTE (FromSiteNo, ToSiteNo, Value) AS
(
SELECT Transfers.FromSiteNo,
Transfers.ToSiteNo,
SUM( Transfers.Value ) AS Value
FROM dbo.Transfers
WHERE Transfers.MoveDate BETWEEN @SessionDateFrom AND @SessionDateTo
AND FromSiteNo <> ToSiteNo
GROUP BY Transfers.FromSiteNo,
Transfers.ToSiteNo
)
SELECT FromCS.No AS SiteNo,
FromCS.Name AS SiteName,
ToCS.No AS OtherSiteNo,
ToCS.Name AS OtherSiteName,
ISNULL( Transfers.Value, 0 ) AS ToFromValue
FROM dbo.CfgSites AS FromCS
LEFT JOIN Transfers_CTE AS Transfers
ON FromCS.No = Transfers.FromSiteNo
LEFT JOIN dbo.CfgSites AS ToCS
ON Transfers.ToSiteNo = ToCS.No
WHERE EXISTS
( SELECT DescendantSites.Descendant
FROM dbo.DescendantSites
WHERE DescendantSites.Parent IN ( @SiteNo )
AND DescendantSites.Descendant = FromCS.No)
ORDER BY FromCS.No
;
- Since
Cs.No
andJoinedSites.No
should not be equal, and they are joined to the From & To values of the CTE, I added the filter in the CTE to exclude any transfers where the To and From site matched. - Your Full Outer Join was effectively a left outer join because any results from the Right side table would have been excluded by the Left side reference of your EXISTS clause.
- You attempt to join transfers to sites from both directions. However, if A = B, then B = A. So if we get all of the
FromSite
joins established to CS on the first pass, there is no reason to do a second pass by joiningJoinedSites
to theFromSite
as they will already have found a match. This change also eliminates the near Cartesian product of joiningCfgSites
to itself. - If we consider the CS table our anchor, understanding it has all of the From Sites included, our problem then becomes how to get the To sites. The relationship between From and To is contained in the Transfers_CTE. Thus we just need to join back to the
CfgSites
using theToSiteNo
field to find the site information. - The Sum aggregate was at the grain of the Transfer relationship, To & From. This is maintained in the changes, but now there is only one value column, returning the Value that was transferred between From and To.
There is no need to join CfgSites
to itself directly, unless you may also need to show any ToFrom combinations that did not get any transfers.
Hopefully this will return your expected results. If not, provide some DDL/DML and I may take another look at it.
Thanks for the feedback. I realised that I haven't been clear enough in the purpose of the script so i have updated my question with, hopefully, a better reflection on what it has to achieve and included the DDL. In relation to point 1, is it worth adding a filter to an event that will only occur 0.01% of the time (through fault)? Would it impact performance if filtering for something it cant find?
– NinjaArekku
Apr 13 '18 at 8:06
add a comment |
Here is an attempt at a rewrite, but you didn't provide any DDL or DML so there is no way for me to test it. I'll list reasons for the changes below.
WITH Transfers_CTE (FromSiteNo, ToSiteNo, Value) AS
(
SELECT Transfers.FromSiteNo,
Transfers.ToSiteNo,
SUM( Transfers.Value ) AS Value
FROM dbo.Transfers
WHERE Transfers.MoveDate BETWEEN @SessionDateFrom AND @SessionDateTo
AND FromSiteNo <> ToSiteNo
GROUP BY Transfers.FromSiteNo,
Transfers.ToSiteNo
)
SELECT FromCS.No AS SiteNo,
FromCS.Name AS SiteName,
ToCS.No AS OtherSiteNo,
ToCS.Name AS OtherSiteName,
ISNULL( Transfers.Value, 0 ) AS ToFromValue
FROM dbo.CfgSites AS FromCS
LEFT JOIN Transfers_CTE AS Transfers
ON FromCS.No = Transfers.FromSiteNo
LEFT JOIN dbo.CfgSites AS ToCS
ON Transfers.ToSiteNo = ToCS.No
WHERE EXISTS
( SELECT DescendantSites.Descendant
FROM dbo.DescendantSites
WHERE DescendantSites.Parent IN ( @SiteNo )
AND DescendantSites.Descendant = FromCS.No)
ORDER BY FromCS.No
;
- Since
Cs.No
andJoinedSites.No
should not be equal, and they are joined to the From & To values of the CTE, I added the filter in the CTE to exclude any transfers where the To and From site matched. - Your Full Outer Join was effectively a left outer join because any results from the Right side table would have been excluded by the Left side reference of your EXISTS clause.
- You attempt to join transfers to sites from both directions. However, if A = B, then B = A. So if we get all of the
FromSite
joins established to CS on the first pass, there is no reason to do a second pass by joiningJoinedSites
to theFromSite
as they will already have found a match. This change also eliminates the near Cartesian product of joiningCfgSites
to itself. - If we consider the CS table our anchor, understanding it has all of the From Sites included, our problem then becomes how to get the To sites. The relationship between From and To is contained in the Transfers_CTE. Thus we just need to join back to the
CfgSites
using theToSiteNo
field to find the site information. - The Sum aggregate was at the grain of the Transfer relationship, To & From. This is maintained in the changes, but now there is only one value column, returning the Value that was transferred between From and To.
There is no need to join CfgSites
to itself directly, unless you may also need to show any ToFrom combinations that did not get any transfers.
Hopefully this will return your expected results. If not, provide some DDL/DML and I may take another look at it.
Here is an attempt at a rewrite, but you didn't provide any DDL or DML so there is no way for me to test it. I'll list reasons for the changes below.
WITH Transfers_CTE (FromSiteNo, ToSiteNo, Value) AS
(
SELECT Transfers.FromSiteNo,
Transfers.ToSiteNo,
SUM( Transfers.Value ) AS Value
FROM dbo.Transfers
WHERE Transfers.MoveDate BETWEEN @SessionDateFrom AND @SessionDateTo
AND FromSiteNo <> ToSiteNo
GROUP BY Transfers.FromSiteNo,
Transfers.ToSiteNo
)
SELECT FromCS.No AS SiteNo,
FromCS.Name AS SiteName,
ToCS.No AS OtherSiteNo,
ToCS.Name AS OtherSiteName,
ISNULL( Transfers.Value, 0 ) AS ToFromValue
FROM dbo.CfgSites AS FromCS
LEFT JOIN Transfers_CTE AS Transfers
ON FromCS.No = Transfers.FromSiteNo
LEFT JOIN dbo.CfgSites AS ToCS
ON Transfers.ToSiteNo = ToCS.No
WHERE EXISTS
( SELECT DescendantSites.Descendant
FROM dbo.DescendantSites
WHERE DescendantSites.Parent IN ( @SiteNo )
AND DescendantSites.Descendant = FromCS.No)
ORDER BY FromCS.No
;
- Since
Cs.No
andJoinedSites.No
should not be equal, and they are joined to the From & To values of the CTE, I added the filter in the CTE to exclude any transfers where the To and From site matched. - Your Full Outer Join was effectively a left outer join because any results from the Right side table would have been excluded by the Left side reference of your EXISTS clause.
- You attempt to join transfers to sites from both directions. However, if A = B, then B = A. So if we get all of the
FromSite
joins established to CS on the first pass, there is no reason to do a second pass by joiningJoinedSites
to theFromSite
as they will already have found a match. This change also eliminates the near Cartesian product of joiningCfgSites
to itself. - If we consider the CS table our anchor, understanding it has all of the From Sites included, our problem then becomes how to get the To sites. The relationship between From and To is contained in the Transfers_CTE. Thus we just need to join back to the
CfgSites
using theToSiteNo
field to find the site information. - The Sum aggregate was at the grain of the Transfer relationship, To & From. This is maintained in the changes, but now there is only one value column, returning the Value that was transferred between From and To.
There is no need to join CfgSites
to itself directly, unless you may also need to show any ToFrom combinations that did not get any transfers.
Hopefully this will return your expected results. If not, provide some DDL/DML and I may take another look at it.
edited yesterday
aduguid
3301318
3301318
answered Apr 12 '18 at 15:11
Wes HWes H
1702
1702
Thanks for the feedback. I realised that I haven't been clear enough in the purpose of the script so i have updated my question with, hopefully, a better reflection on what it has to achieve and included the DDL. In relation to point 1, is it worth adding a filter to an event that will only occur 0.01% of the time (through fault)? Would it impact performance if filtering for something it cant find?
– NinjaArekku
Apr 13 '18 at 8:06
add a comment |
Thanks for the feedback. I realised that I haven't been clear enough in the purpose of the script so i have updated my question with, hopefully, a better reflection on what it has to achieve and included the DDL. In relation to point 1, is it worth adding a filter to an event that will only occur 0.01% of the time (through fault)? Would it impact performance if filtering for something it cant find?
– NinjaArekku
Apr 13 '18 at 8:06
Thanks for the feedback. I realised that I haven't been clear enough in the purpose of the script so i have updated my question with, hopefully, a better reflection on what it has to achieve and included the DDL. In relation to point 1, is it worth adding a filter to an event that will only occur 0.01% of the time (through fault)? Would it impact performance if filtering for something it cant find?
– NinjaArekku
Apr 13 '18 at 8:06
Thanks for the feedback. I realised that I haven't been clear enough in the purpose of the script so i have updated my question with, hopefully, a better reflection on what it has to achieve and included the DDL. In relation to point 1, is it worth adding a filter to an event that will only occur 0.01% of the time (through fault)? Would it impact performance if filtering for something it cant find?
– NinjaArekku
Apr 13 '18 at 8:06
add a comment |
Thanks for contributing an answer to Code Review 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.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2fcodereview.stackexchange.com%2fquestions%2f191864%2fquery-to-show-each-sites-stock-transfer-history-between-all-other-sites%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
Can you elaborate on this part:
WHERE DescendantSites.Parent IN(@SiteNo)
I'm assuming this is a delimited list? If not, you can simply use=
– scsimon
Apr 12 '18 at 13:23
@scsimon the parameter SiteNo can be multiple values or just a single entry. It allows the customer to view any selected sites they want.
– NinjaArekku
Apr 12 '18 at 13:52