SQL Aggregate query where data is in a join table that may or may not have records











up vote
1
down vote

favorite












Background: I have a system that keeps track of inventory that is ordered and shipped to various places. There is an Inventory table that contains all the inventory specific properties and how much was initially ordered for each item:



Inventory Table



CREATE TABLE Inventory
(
InventoryID int,
InventoryName varchar,
AmtOrdered float,
Weight float,
Color string
)


Then I have an InventoryTransportation table that acts as a historical record of the movement of those Ordered items as they reach an end point



InventoryTransportation Table



CREATE TABLE InventoryTransportation
(
InventoryTransportationId int,
fkInventoryId int,
AmtTransported float,
FromLocation string,
ToLocation string
)


There are defined locations that these items move through to get to a final location. (Vendor -> Warehouse, Vendor -> Site, Warehouse -> Site, Warehouse -> Vendor, Site -> Vendor).



The columns I need to calculate are Qty at Vendor, Qty At Warehouse and Qty At Site.



Currently, I am just returning all the historical data and calculating these values in my business layer. But it would be so much easier if I just did this on the database side which would probably do this much more efficiently than I am doing.



The way I calculate things now is:




Qty At Vendor = AmtOrdered + Sum(AmtTransported where ToLocation =
Vendor) - Sum(AmtTransported where FromLocation = Vendor)



Qty At Warehouse = Sum(AmtTransported where ToLocation = Warehouse) -
Sum(AmtTransported where FromLocation = Warehouse)



Qty At Site = Sum(AmtTransported where ToLocation = Site) -
Sum(AmtTransported where FromLocation = Site)




Question
Is there a way to write a query that would return the Sums as columns associated with the Inventory record that they belong to?



I started with doing Left Join subqueries to do calculations, but I dont know how to do the aggregate sum with the +if its from a location or -if its to a location portion of the formula and I dont know how to return multiple columns from that sub query (or if I have to use multiple sub queries) for each of the quantities.



I think to do the multiple columns, I have to figure out how to use the SQL Pivot command, but I haven't exactly wrapped my head around how to use that.



Any help would be greatly appreciated



UPDATE
Currently, to do this, I added a series of LeftJoins to calculate each individual metric separately. It works but I don't know if it's the right way to do this.



SELECT
Ordered = ps.quantity
,[@Vendor] = ps.Quantity - COALESCE(psrToVendor.ToVendor, 0) - COALESCE(psrFromVendor.FromVendor, 0)
FROM Project.ProjectSpec ps
LEFT JOIN
(
SELECT
psrd.ProjectSpecID
,ToVendor = SUM(psrd.QuantityReceived)
FROM Project.ProjectSpecReceivedDetails psrd
WHERE
psrd.Deleted = 0
AND psrd.ToProjectSpecLocationID = 1
GROUP BY psrd.ProjectSpecID
) psrToVendor ON psrToVendor.ProjectSpecID = ps.ID
LEFT JOIN
(
SELECT
psrd.ProjectSpecID
,FromVendor = SUM(psrd.QuantityReceived)
FROM Project.ProjectSpecReceivedDetails psrd
WHERE
psrd.Deleted = 0
AND psrd.FromProjectSpecLocationID = 1
GROUP BY psrd.ProjectSpecID
) psrFromVendor ON psrFromVendor.ProjectSpecID = ps.ID









share|improve this question




























    up vote
    1
    down vote

    favorite












    Background: I have a system that keeps track of inventory that is ordered and shipped to various places. There is an Inventory table that contains all the inventory specific properties and how much was initially ordered for each item:



    Inventory Table



    CREATE TABLE Inventory
    (
    InventoryID int,
    InventoryName varchar,
    AmtOrdered float,
    Weight float,
    Color string
    )


    Then I have an InventoryTransportation table that acts as a historical record of the movement of those Ordered items as they reach an end point



    InventoryTransportation Table



    CREATE TABLE InventoryTransportation
    (
    InventoryTransportationId int,
    fkInventoryId int,
    AmtTransported float,
    FromLocation string,
    ToLocation string
    )


    There are defined locations that these items move through to get to a final location. (Vendor -> Warehouse, Vendor -> Site, Warehouse -> Site, Warehouse -> Vendor, Site -> Vendor).



    The columns I need to calculate are Qty at Vendor, Qty At Warehouse and Qty At Site.



    Currently, I am just returning all the historical data and calculating these values in my business layer. But it would be so much easier if I just did this on the database side which would probably do this much more efficiently than I am doing.



    The way I calculate things now is:




    Qty At Vendor = AmtOrdered + Sum(AmtTransported where ToLocation =
    Vendor) - Sum(AmtTransported where FromLocation = Vendor)



    Qty At Warehouse = Sum(AmtTransported where ToLocation = Warehouse) -
    Sum(AmtTransported where FromLocation = Warehouse)



    Qty At Site = Sum(AmtTransported where ToLocation = Site) -
    Sum(AmtTransported where FromLocation = Site)




    Question
    Is there a way to write a query that would return the Sums as columns associated with the Inventory record that they belong to?



    I started with doing Left Join subqueries to do calculations, but I dont know how to do the aggregate sum with the +if its from a location or -if its to a location portion of the formula and I dont know how to return multiple columns from that sub query (or if I have to use multiple sub queries) for each of the quantities.



    I think to do the multiple columns, I have to figure out how to use the SQL Pivot command, but I haven't exactly wrapped my head around how to use that.



    Any help would be greatly appreciated



    UPDATE
    Currently, to do this, I added a series of LeftJoins to calculate each individual metric separately. It works but I don't know if it's the right way to do this.



    SELECT
    Ordered = ps.quantity
    ,[@Vendor] = ps.Quantity - COALESCE(psrToVendor.ToVendor, 0) - COALESCE(psrFromVendor.FromVendor, 0)
    FROM Project.ProjectSpec ps
    LEFT JOIN
    (
    SELECT
    psrd.ProjectSpecID
    ,ToVendor = SUM(psrd.QuantityReceived)
    FROM Project.ProjectSpecReceivedDetails psrd
    WHERE
    psrd.Deleted = 0
    AND psrd.ToProjectSpecLocationID = 1
    GROUP BY psrd.ProjectSpecID
    ) psrToVendor ON psrToVendor.ProjectSpecID = ps.ID
    LEFT JOIN
    (
    SELECT
    psrd.ProjectSpecID
    ,FromVendor = SUM(psrd.QuantityReceived)
    FROM Project.ProjectSpecReceivedDetails psrd
    WHERE
    psrd.Deleted = 0
    AND psrd.FromProjectSpecLocationID = 1
    GROUP BY psrd.ProjectSpecID
    ) psrFromVendor ON psrFromVendor.ProjectSpecID = ps.ID









    share|improve this question


























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      Background: I have a system that keeps track of inventory that is ordered and shipped to various places. There is an Inventory table that contains all the inventory specific properties and how much was initially ordered for each item:



      Inventory Table



      CREATE TABLE Inventory
      (
      InventoryID int,
      InventoryName varchar,
      AmtOrdered float,
      Weight float,
      Color string
      )


      Then I have an InventoryTransportation table that acts as a historical record of the movement of those Ordered items as they reach an end point



      InventoryTransportation Table



      CREATE TABLE InventoryTransportation
      (
      InventoryTransportationId int,
      fkInventoryId int,
      AmtTransported float,
      FromLocation string,
      ToLocation string
      )


      There are defined locations that these items move through to get to a final location. (Vendor -> Warehouse, Vendor -> Site, Warehouse -> Site, Warehouse -> Vendor, Site -> Vendor).



      The columns I need to calculate are Qty at Vendor, Qty At Warehouse and Qty At Site.



      Currently, I am just returning all the historical data and calculating these values in my business layer. But it would be so much easier if I just did this on the database side which would probably do this much more efficiently than I am doing.



      The way I calculate things now is:




      Qty At Vendor = AmtOrdered + Sum(AmtTransported where ToLocation =
      Vendor) - Sum(AmtTransported where FromLocation = Vendor)



      Qty At Warehouse = Sum(AmtTransported where ToLocation = Warehouse) -
      Sum(AmtTransported where FromLocation = Warehouse)



      Qty At Site = Sum(AmtTransported where ToLocation = Site) -
      Sum(AmtTransported where FromLocation = Site)




      Question
      Is there a way to write a query that would return the Sums as columns associated with the Inventory record that they belong to?



      I started with doing Left Join subqueries to do calculations, but I dont know how to do the aggregate sum with the +if its from a location or -if its to a location portion of the formula and I dont know how to return multiple columns from that sub query (or if I have to use multiple sub queries) for each of the quantities.



      I think to do the multiple columns, I have to figure out how to use the SQL Pivot command, but I haven't exactly wrapped my head around how to use that.



      Any help would be greatly appreciated



      UPDATE
      Currently, to do this, I added a series of LeftJoins to calculate each individual metric separately. It works but I don't know if it's the right way to do this.



      SELECT
      Ordered = ps.quantity
      ,[@Vendor] = ps.Quantity - COALESCE(psrToVendor.ToVendor, 0) - COALESCE(psrFromVendor.FromVendor, 0)
      FROM Project.ProjectSpec ps
      LEFT JOIN
      (
      SELECT
      psrd.ProjectSpecID
      ,ToVendor = SUM(psrd.QuantityReceived)
      FROM Project.ProjectSpecReceivedDetails psrd
      WHERE
      psrd.Deleted = 0
      AND psrd.ToProjectSpecLocationID = 1
      GROUP BY psrd.ProjectSpecID
      ) psrToVendor ON psrToVendor.ProjectSpecID = ps.ID
      LEFT JOIN
      (
      SELECT
      psrd.ProjectSpecID
      ,FromVendor = SUM(psrd.QuantityReceived)
      FROM Project.ProjectSpecReceivedDetails psrd
      WHERE
      psrd.Deleted = 0
      AND psrd.FromProjectSpecLocationID = 1
      GROUP BY psrd.ProjectSpecID
      ) psrFromVendor ON psrFromVendor.ProjectSpecID = ps.ID









      share|improve this question















      Background: I have a system that keeps track of inventory that is ordered and shipped to various places. There is an Inventory table that contains all the inventory specific properties and how much was initially ordered for each item:



      Inventory Table



      CREATE TABLE Inventory
      (
      InventoryID int,
      InventoryName varchar,
      AmtOrdered float,
      Weight float,
      Color string
      )


      Then I have an InventoryTransportation table that acts as a historical record of the movement of those Ordered items as they reach an end point



      InventoryTransportation Table



      CREATE TABLE InventoryTransportation
      (
      InventoryTransportationId int,
      fkInventoryId int,
      AmtTransported float,
      FromLocation string,
      ToLocation string
      )


      There are defined locations that these items move through to get to a final location. (Vendor -> Warehouse, Vendor -> Site, Warehouse -> Site, Warehouse -> Vendor, Site -> Vendor).



      The columns I need to calculate are Qty at Vendor, Qty At Warehouse and Qty At Site.



      Currently, I am just returning all the historical data and calculating these values in my business layer. But it would be so much easier if I just did this on the database side which would probably do this much more efficiently than I am doing.



      The way I calculate things now is:




      Qty At Vendor = AmtOrdered + Sum(AmtTransported where ToLocation =
      Vendor) - Sum(AmtTransported where FromLocation = Vendor)



      Qty At Warehouse = Sum(AmtTransported where ToLocation = Warehouse) -
      Sum(AmtTransported where FromLocation = Warehouse)



      Qty At Site = Sum(AmtTransported where ToLocation = Site) -
      Sum(AmtTransported where FromLocation = Site)




      Question
      Is there a way to write a query that would return the Sums as columns associated with the Inventory record that they belong to?



      I started with doing Left Join subqueries to do calculations, but I dont know how to do the aggregate sum with the +if its from a location or -if its to a location portion of the formula and I dont know how to return multiple columns from that sub query (or if I have to use multiple sub queries) for each of the quantities.



      I think to do the multiple columns, I have to figure out how to use the SQL Pivot command, but I haven't exactly wrapped my head around how to use that.



      Any help would be greatly appreciated



      UPDATE
      Currently, to do this, I added a series of LeftJoins to calculate each individual metric separately. It works but I don't know if it's the right way to do this.



      SELECT
      Ordered = ps.quantity
      ,[@Vendor] = ps.Quantity - COALESCE(psrToVendor.ToVendor, 0) - COALESCE(psrFromVendor.FromVendor, 0)
      FROM Project.ProjectSpec ps
      LEFT JOIN
      (
      SELECT
      psrd.ProjectSpecID
      ,ToVendor = SUM(psrd.QuantityReceived)
      FROM Project.ProjectSpecReceivedDetails psrd
      WHERE
      psrd.Deleted = 0
      AND psrd.ToProjectSpecLocationID = 1
      GROUP BY psrd.ProjectSpecID
      ) psrToVendor ON psrToVendor.ProjectSpecID = ps.ID
      LEFT JOIN
      (
      SELECT
      psrd.ProjectSpecID
      ,FromVendor = SUM(psrd.QuantityReceived)
      FROM Project.ProjectSpecReceivedDetails psrd
      WHERE
      psrd.Deleted = 0
      AND psrd.FromProjectSpecLocationID = 1
      GROUP BY psrd.ProjectSpecID
      ) psrFromVendor ON psrFromVendor.ProjectSpecID = ps.ID






      sql azure-sql-database






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 2 days ago









      digital.aaron

      2,9301128




      2,9301128










      asked 2 days ago









      JakeHova

      305320




      305320





























          active

          oldest

          votes











          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',
          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%2f53414650%2fsql-aggregate-query-where-data-is-in-a-join-table-that-may-or-may-not-have-recor%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53414650%2fsql-aggregate-query-where-data-is-in-a-join-table-that-may-or-may-not-have-recor%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

          Catalogne

          Violoncelliste

          Héron pourpré