Is it possible to SUM grouped rows into another column but only show the sum result on 1 of the rows? - sql

I have a query table which includes data from several tables Joined with LEFT JOIN. So far everything works, with the resulting data being the individual items from Sales Orders. I can pull through the Total Sales Order Value into a column, but I only want this to be displayed on 1 of the rows for that Order OR into a separate row to represent the whole order.
My thoughts are that either I pull through the total but somehow only do this if it doesn't already appear for that order already OR I use SUM() but this seems to only work if used with GROUP BY and then I only get shown the totals and not the individual items.
I don't really know what to try as I don't even know if this is possible, and internet searches are not giving me any results that seem to help, they are all about Grouping.
SELECT
so."Sales Order#" as 'Sales Order Number',
soi."Sub Total" as 'Sub-Total'
FROM
"Sales Order Items" AS "soi"
LEFT JOIN
"Sales Orders" AS "so" ON so."Sales order ID" = soi."Sales order ID"
I would like to add a column 'TCV' which SUMS the 'Sub Total' values from all items that have the same Sales Order Number. But I only want this sub-total to show once per Order (not against every order item).

You can easily achieve this by using window functions in a case stmt:
SELECT
so.SalesOrderNumber as 'Sales Order Number',
CASE WHEN LAG(so.id) OVER (PARITION BY so.salesOrderNumber ORDER BY so.id) IS NULL --this row is first in group, order however you determine "First"
THEN soi.SubTotal
ELSE NULL
END AS subTotal
FROM
"Sales Order Items" AS soi LEFT JOIN
"Sales Orders" AS so ON so.salesOrderId = soi.salesOrderId

To create an additional row with the sum
Duplicate the query
Group the query by order
Sum the line value column
Use a Union to add this new query to the original.
Add an additional column to both, hard code the first to 'lines' and second to 'order'
You can add a total column
Duplicate the query
Group the query by order
Sum the line value column
Put the new query in the from clause of the original, give it an alias
Join the query by order number
Add the sum column of the new query to the select clause of the first query
Optionally, you can use use case statements to only show it for one line.

Related

How to work past "At most one record can be returned by this subquery"

I'm having trouble understanding this error through all the researching I have done. I have the following query
SELECT M.[PO Concatenate], Sum(M.SumofAward) AS TotalAward, (SELECT TOP 1 M1.[Material Group] FROM
[MGETCpreMG] AS M1 WHERE M1.[PO Concatenate]=M.[PO Concatenate] ORDER BY M1.SumofAward DESC) AS TopGroup
FROM MGETCpreMG AS M
GROUP BY M.[PO Concatenate];
For a brief instance it reviews the results I want, but then the "At most one record can be returned by this subquery" error comes and wipes all the data to #Name?
For context, [MGETCpreMG] is a query off a main table [MG ETC] that was used to consolidate Award for differing Material Groups on a PO transaction ([PO Concatenate])
SELECT [MG ETC].[PO Concatenate], Sum([MG ETC].Award) AS SumOfAward, [MG ETC].[Material Group]
FROM [MG ETC]
GROUP BY [MG ETC].[PO Concatenate], [MG ETC].[Material Group]
ORDER BY [MG ETC].[PO Concatenate];
I'm thinking it lies in my inability to understand how to utilize a subquery.
In the case in which the query can return more then one value? Simply add an additonal sort by.
So, a common sub query might be to get the last invoice. So you might have:
select ID, CompanyName,
(SELECT TOP 1 InvoiceDate from tblInvoice
where tblInvoice.CustomerID = tblCompany.ID
Order by InvoiceDate DESC)
As LastInvoiceDate
From tblCustomers
Now the above might work for some time, but then it will blow up since you might have two invoices for the same day!
So, all you have to do is add that extra order by clause - say on the PK of the child table like this:
Order by InvoiceDate DESC,ID DESC)
So top 1 will respect the "additional" order columns you add, and thus only ever return one row - even if there are multiple values that match the top 1 column.
I suppose in the above we could perhaps forget the invoiceDate and always take the top most last autonumber ID, but for a lot of queries, you can't always be sure - it might be we want the last most expensive invoice amount. And again, if the max value (top) was the same for two large invoice amounts, then again two rows could be return. So, simply add the extra ORDER BY clause with an 2nd column that further orders the data. And thus top 1 will only pull the first value. Your example of a top group is such an example. Just tack on the extra order by "ID" or whatever the auto number ID column is.

Grouping records from one table into one

Basically, I'm trying to retrieve only 1 record from a table based on catalog_no and packing_list_no. However, the table I'm retrieving the information from has additional details that I don't need but makes the 1 record I need into 3 distinct records.
I tried summing and grouping the info, but I'm still getting 3 records instead of 1.
Any ideas of how to solve this issue?
Your GROUP BY groups your result on the columns quantity picked, quantity shipped and weight shipped. A different value in any of those columns will result into a different row.
You can drop the GROUP BY clause all together, if the desirable result is the packing list and catalog no that you have specified. You can use the GROUP BY clause to columns that you do not use sum to group the result set.
SELECT catalog_no, sum(qty_picked), sum(qty_shipped), sum(weight_shipped), packing_list_no, bay_no, carrier_code, tracking_no FROM oeorder_shipping
WHERE packing_list_no='CP12618525' AND catalog_no='437656500'
GROUP BY bay_no, carrier_code, tracking_no;

SQL SUM function with added

total novice here with SQL SUM function question. So, SUM function itself works as I expected it to:
select ID, sum(amount)
from table1
group by ID
There are several records for each ID and my goal is to summarize each ID on one row where the next column would give me the summarized amount of column AMOUNT.
This works fine, however I also need to filter out based on certain criteria in the summarized amount field. I.e. only look for results where the summarized amount is either bigger, smaller or between certain number.
This is the part I'm struggling with, as I can't seem to use column AMOUNT, as this messes up summarizing results.
Column name for summarized results is shown as "00002", however using this in the between or > / < clause does not work either. Tried this:
select ID, sum(amount)
from table1
where 00002 > 1000
group by ID
No error message, just blank result, however plenty of summarized results with values over 1000.
Unfortunately not sure on the engine the database runs on, however it should be some IBM-based product.
The WHERE clause will filter individual rows that don't match the condition before aggregating them.
If you want to do post aggregation filtering you need to use the HAVING Clause.
HAVING will apply the filter to the results after being grouped.
select ID, sum(amount)
from table1
group by ID
having sum(amount) > 1000

Is GROUP BY needed in the following correlated subquery?

Given scenario:
table fd
(cust_id, fd_id) primary-key and amount
table loan
(cust_id, l_id) primary-key and amount
I want to list all customers who have a fixed deposit with an amount less than the sum of all their loans.
Query:
SELECT cust_id
FROM fd
WHERE amount
<
(SELECT sum(amount)
FROM loan
WHERE fd.cust_id = loan.cust_id);
OR should we use
SELECT cust_id
FROM fd
WHERE amount
<
(SELECT sum(amount)
FROM loan
WHERE fd.cust_id = loan.cust_id group by cust_id);
A customer can have multiple loans but one FD is considered at a time.
GROUP BY can be omitted in this case, because there is only (one) aggregate function(s) in the SELECT list and all rows are guaranteed to belong to the same group of cust_id ( by the WHERE clause).
The aggregation will be over all rows with matching cust_id in both cases. So both queries are correct.
This would be a cleaner another way to implement the same thing:
SELECT fd.cust_id
FROM fd
JOIN loan USING (cust_id)
GROUP BY fd.cust_id, fd.amount
HAVING fd.amount < sum(loan.amount)
There is one difference: rows with identical (cust_id, amount) in fd only appear once in the result of my query, while they would appear multiple times in the original.
Either way, if there is no matching row with a non-null amount in table loan, you get no rows at all. I assume you are aware of that.
There are no need for GROUP BY since you filtered data by cust_id. In any case inner query will return the same result.
No, it isn't, because you calculate sum(amount) for customer with id = fd.cust_id, so for a single customer.
However, if somehow your subquery calculate sum for more than one customer, the group by would cause the subquery to generate more than one row and this will cause the condition(<) to fail, and thus, the query to fail.
A query with an aggregate like sum but without a group by will output one group. The aggregates will be computed over all matching rows.
A subquery in a condition clause is only allowed to return one row. If the subquery returned multiple rows, what would the following expression mean?
where 1 > (... subquery ...)
So the group by must be omitted; you would even get an error for your second query.
N.B. When you specify all, any, or some a subquery can return multiple rows:
where 1 > ALL (... subquery ...)
But it's easy to see why that doesn't make sense in your case; you'd compare one customer's data to that of another.

order by and group by mysql

tell some big, diff between order by and group by,
like sort columns data=>order by
group it by similar data used for aggregation , order by could be used inside the grouped items ,
please Tell 5 diff
The order by clause is used to order your data set. For example,
select *
from customers
order by customer_id asc
will give you a list of customers in order of customer id from lowest to highest.
The group by clause is used to aggregate your data. For example,
select customer_id, sum(sale_price), max(sale_price)
from customers
group by customer_id
order by customer_id asc
will give you each customer along with their total sales and maximum sale, again ordered by customer id.
In other words, grouping allows you to combine multiple rows from the database into a single output row, based on some criteria, and select functions of those fields not involved in the grouping (minimum, maximum, total, average and so on).
group by groups data by one or more columns, and order by orders the data by one or more columns? i don't really get the question?
using group by is similar to select distinct in the aspect that only unique values for the given values will be returned. furthermore you can use aggregate functions to calculate e.g. the sum for each group.
what do you want to hear? tell me five differences between apples and oranges?