Unexpected result from the COUNT syntax - sql

I would like to show the number of rows of two columns which belonging to two tables. However, the result is not I expected. I am really confused about that. Could you please advice? Thanks.
SELECT COUNT(TABLE1.INTEREST) FROM INCOME; // RESULT = 10
SELECT COUNT(TABLE2.LOAN) FROM EXPEND; //RESULT = 10
SELECT COUNT(TABLE1.INTEREST), COUNT(TABLE2.LOAN) FROM INCOME, EXPEND; //RESULT = 100
Why the result is "100|100" if I execute the third SQL command? I expect the result is "10|10".

A cartesian product is performed in your last query.

It's because you are joining every row of INCOME onto every row of EXPEND (called a cartesian product)
Instead of doing FROM INCOME, EXPEND you need to do something like
FROM INCOME
JOIN EXPEND
ON Income.SomeColumn = Expend.SomeColumn
or add a where clause to your current query:
FROM INCOME, EXPEND
WHERE Income.SomeColumn = Expend.SomeColumn

Related

How do I do a sum per id?

SELECT distinct
A.PROPOLN, C.LIFCLNTNO, A.PROSASORG, sum (A.PROSASORG) as sum
FROM [FPRODUCTPF] A
join [FNBREQCPF] B on (B.IQCPLN=A.PROPOLN)
join [FLIFERATPF] C on (C.LIFPOLN=A.PROPOLN and C.LIFPRDCNT=A.PROPRDCNT and C.LIFBNFCNT=A.PROBNFCNT)
where C.LIFCLNTNO='2012042830507' and A.PROSASORG>0 and A.PROPRDSTS='10' and
A.PRORECSTS='1' and A.PROBNFLVL='M' and B.IQCODE='B10000' and B.IQAPDAT>20180101
group by C.LIFCLNTNO, A.PROPOLN, A.PROSASORG
This does not sum correctly, it returns two lines instead of one:
PROPOLN LIFCLNTNO PROSASORG sum
1 209814572 2012042830507 3881236 147486968
2 209814572 2012042830507 15461074 463832220
You are seeing two rows because A.PROSASORG has two different values for the "C.LIFCLNTNO, A.PROPOLN" grouping.
i.e.
C.LIFCLNTNO, A.PROPOLN, A.PROSASORG together give you two unique rows.
If you want a single row for C.LIFCLNTNO, A.PROPOLN, then you may want to use an aggregate on A.PROSASORG as well.
Your entire query is being filtered on your "C" table by the one LifClntNo,
so you can leave that out of your group by and just have it as a MAX() value
in your select since it will always be the same value.
As for you summing the PROSASORG column via comment from other answer, just sum it. Hour column names are not evidently clear for purpose, so I dont know if its just a number, a quantity, or whatever. You might want to just pull that column out of your query completely if you want based on a single product id.
For performance, I would suggest the following indexes on
Table Index
FPRODUCTPF ( PROPRDSTS, PRORECSTS, PROBNFLVL, PROPOLN )
FNBREQCPF ( IQCODE, IQCPLN, IQAPDAT )
FLIFERATPF ( LIFPOLN, LIFPRDCNT, LIFBNFCNT, LIFCLNTNO )
I have rewritten your query to put the corresponding JOIN components to the same as the table they are based on vs all in the where clause.
SELECT
P.PROPOLN,
max( L.LIFCLNTNO ) LIFCLNTNO,
sum (P.PROSASORG) as sum
FROM
[FPRODUCTPF] P
join [FNBREQCPF] N
on N.IQCODE = 'B10000'
and P.PROPOLN = N.IQCPLN
and N.IQAPDAT > 20180101
join [FLIFERATPF] L
on L.LIFCLNTNO='2012042830507'
and P.PROPOLN = L.LIFPOLN
and P.PROPRDCNT = L.LIFPRDCNT
and P.PROBNFCNT = L.LIFBNFCNT
where
P.PROPRDSTS = '10'
and P.PRORECSTS = '1'
and P.PROBNFLVL = 'M'
and P.PROSASORG > 0
group by
P.PROPOLN
Now, one additional issue you will PROBABLY be running into. You are doing a query with multiple joins, and it appears that there will be multiple records in EACH of your FNBREQCPF and FLIFERATPF tables for the same FPRODUCTPF entry. If you, you will be getting a Cartesian result as the PROSASORG value will be counted for each instance combination in the two other tables.
Ex: FProductPF has ID = X with a Prosasorg value of 3
FNBreQCPF has matching records of Y1 and Y2
FLIFERATPF has matching records of Z1, Z2 and Z3.
So now your total will be equal to 3 times 6 = 18.
If you look at the combinations, Y1:Z1, Y1:Z2, Y1:Z3 AND Y2:Z1, Y2:Z2, Y2:Z3 giving your 6 entries that qualify, times the original value of 3, thus bloating your numbers -- IF such multiple records may exist in each respective table. Now, imagine if your tables have 30 and 40 matching instances respectively, you have just bloated your totals by 1200 times.

SQL Aggregate Function over partitions

I'm relatively new to SQL but have learned some cool stuff. I'm getting results that don't make sense. I've got a query with several subqueries and what-not but I have a windowed function that isn't working like I'm expecting.
The part that isn't working is this (simplified from the 300 line query):
SELECT AVG(table.sales_amount)
OVER (PARTITION BY table.month, table.sales_rep, table.department)
FROM table
The problem is that when I pull the data non aggregated I get a value different (107) than the above returns (95).
I've used windowed functions for COUNT and SUM and they work fine, but AVG is acting strangely. Am I missing something about how this works with AVG?
The subquery that table is a standin for looks like:
sales_rep, month, department, sales_amount
1, 2017-1, abc, 125.20
1, 2017-2, abc, 120.00
2, 2017-1, def, 100.00
...etc
Working out of Sql Server Management studio
SOLVED: I did finally figure it out, the results i was joining this subquery to had the sales rep multiple times in a month selling objects A&B which caused whoever sold both to be counted twice. whoops, my bad.
The results that you get should be the same values as in:
SELECT AVG(table.sales_amount)
FROM table
GROUP BY table.month, table.sales_rep, table.department;
Of course, the rows will be different. You need to match up the three key columns.
Based on your sample data, it looks like the partitioning keys uniquely define each row. Perhaps you really intend:
SELECT AVG(table.sales_amount) OVER () as overall_average
FROM table;
EDIT:
For the departmental average:
SELECT AVG(table.sales_amount) OVER (partition by table.department) as department_average
FROM table;
After some bruteforcing of potential errors I finally figured out the issue. I was joining that subquery to the another which had multiple instances of a sales_rep in a given month (selling objects a & b) which caused the average of those with sales of both objects to be counted twice instead of once.
so sales rep 1 sold objects a & b which made his avg count as 66% of the dept avg instead of 50%, and sales rep 2 count only 33%.

SQL Calculations over tables

There are 2 tables, there is an expected result, the result is to have the total cost of each engagement calculated, there are multiple tests taken during each engagement, each test ranges in cost (all set values), the expected result must be in terms of EngagementId, EngagementCost
The 2 tables, with there respective fields
- EngagementTest (EngagementId, TestId)
- Test (TestId, TestCost)
How would one go calculating the cost of each engagement.
This is as far as i managed to get
SELECT EngagementId, COUNT(TESTId)
FROM EngagementTest
GROUP BY EngagementId;
Try a SUM of the TestCost column rather than a COUNT. COUNT just tells you the number of rows. SUM adds up the values within the rows and gives you a total. Also your existing query doesn't actually use the table that contains the cost data. You can INNER JOIN the two tables via TestId and then GROUP BY the EngagementId so you get the sum of each engagement.
Something like this:
SELECT
ET.EngagementId,
SUM(T.TestCost)
FROM
EngagementTest ET
INNER JOIN Test T
ON T.TestId = ET.TestId
GROUP BY
ET.EngagementId
It can be achieved using below query.
SELECT i.EngagementId, SUM(TestCost)
FROM EngagementTest i
INNER JOIN Test t
ON e.TestId = t.TestId
GROUP BY i.EngagementId

Get the product of two values from two different tables

If anyone can help me figure out where I am going wrong with this SQL that would be great. Please see my attempt to answer it below. I have answer how I think it should be answered but I am very confused by the exam advice below, which says I should use a SUM function? I have googled this and I do not see how a SUM function can help here when I need get the product of two values in this case. Or am I missing something major?
Question: TotalValue is a column in Order relation that contains derived data representing total value (amount) of each order. Write a SQL SELECT statement that computes a value for this column.
My answer:
SELECT Product.ProductPrice * OrderLine.QuantityOrdered AS Total_Value
FROM Product,
OrderLine
GROUP BY Product;
Advice from exam paper:
This is a straightforward question. Tip: you need to use the SUM function. Also, note that you can take the sum of various records set using the GROUP BY clause.
Ok your question became a lot clearer once I clicked on the the hyperlink (blue text).
Each order is going to be made up of a quantity of 1 or more products.
So there could be 3 Product A and 5 Product B etc.
So you have to get the total for each product which is your Price * Quantity, but then you need to add them all together which is where the SUM comes in.
Example:
3 * ProductA Price (e.g. €5) = 15
5 * ProductB Price (e.g. €4) = 20
Total Value = 35
So you need to use the Product, Order and OrderLine tables.
Something like (I haven't tested it):
SELECT SUM(Product.ProductPrice * OrderLine.QuantityOrdered) FROM Product, Order, OrderLine
WHERE Order.OrderID = OrderLine.OrderID
AND Product.ProductID = OrerLine.ProductID
GROUP BY Order.OrderID
This should return rows containing the totalValue for each order - the GROUP BY clause causes the SUM to SUM over each group - not the entire rows.
For a single order you would need add (before the GROUP BY) "AND Order.OrderID = XXXXX" where XXXXX is the actual orders OrderId.

MS Access - Summing up a field to be used in another query is "duplicating" data

I am trying to sum up one field and use it in another query, but when I use the Totals button and then call that sum from the other query it considers that field as multiple instances but with the sum value in each one. How can I sum two fields in two different queries and then use those sums in another query? Note - I only separated them into 3 queries because I felt it would help me avoid "is not part of an aggregate function" errors.
Example Data
Inventory Query: This query groups by item and sums the qty_on_hand field
Item SumOfqty_on_hand
A 300
Job Material query: This query groups on the job's materials and sums up the qty_req field (quantity required to complete the job)
Item SumOfqty_req
A 500
When I make a third query to do the calculation [SumOfqty_req]-[SumOfqty_on_hand] the query does the calculation but for each record in the Job Material query.
Job Material Query
SELECT dbo_jobmatl.item,
IIf(([qty_released]-[qty_complete])<0,0,([qty_released]-[qty_complete]))*[matl_qty] AS qty_req
FROM new_BENInventory
INNER JOIN (dbo_jobmatl
INNER JOIN new_BENJobs
ON (new_BENJobs.suffix = dbo_jobmatl.suffix)
AND (dbo_jobmatl.job = new_BENJobs.job)
) ON new_BENInventory.item = dbo_jobmatl.item
GROUP BY dbo_jobmatl.item,
IIf(([qty_released]-[qty_complete])<0,0,([qty_released]-[qty_complete]))*[matl_qty];
Inventory Query
SELECT dbo_ISW_LPItem.item,
Sum(dbo_ISW_LPItem.qty_on_hand) AS SumOfqty_on_hand,
dbo_ISW_LP.whse,
dbo_ISW_LPItem.hold_flag
FROM (dbo_ISW_LP INNER JOIN dbo_ISW_LPItem
ON dbo_ISW_LP.lp_num = dbo_ISW_LPItem.lp_num)
INNER JOIN dbo_ISW_LPLot
ON (dbo_ISW_LPItem.lp_num = dbo_ISW_LPLot.lp_num)
AND (dbo_ISW_LPItem.item = dbo_ISW_LPLot.item)
AND (dbo_ISW_LPItem.qty_on_hand = dbo_ISW_LPLot.qty_on_hand)
GROUP BY dbo_ISW_LPItem.item,
dbo_ISW_LP.whse,
dbo_ISW_LPItem.hold_flag
HAVING (((Sum(dbo_ISW_LPItem.qty_on_hand))>0)
AND ((dbo_ISW_LP.whse) Like "BEN")
AND ((dbo_ISW_LPItem.hold_flag) Like 0));
Third Query
SELECT new_BENJobItems.item,
[qty_req]-[SumOfqty_on_hand] AS [Transfer QTY]
FROM new_BENInventory
INNER JOIN new_BENJobItems
ON new_BENInventory.item = new_BENJobItems.item;
Please note that anything that starts with dbo_ is a prefix for a table that sources the original data.
If any more clarification is needed I would be more than happy to provide it.
Looks like you need a GROUP BY new_BENJobItems.item on your final query along with a SUM() on the quantity. Or to remove the IIf(([qty_released]-[qty_complete])<0,0,([qty_released]-[qty_complete]))*[matl_qty] from your Job Material query. Or both. As written, the Job Material Query is going to return a record for every different key value in the joined input tables that has a distinct quantity, which doesn't seem like the granularity you want for that.