I have a query that I'm trying to perform below. However, being unable to test my query, I am unsure of my result.
The donors who have donated at least $10,000 since January 1, 2010 (donor ID, name, total
gifts).
SELECT donor_id,
donor_name,
SUM (amount) AS total_gifts_since_2010
FROM donor
JOIN gift
USING (donor_id)
JOIN gift_fund_allocation
USING (gift_id)
JOIN fund
USING (fund_id)
WHERE gift_date >= ‘01/01/2010'
GROUP BY (donor_id, donor_name)
HAVING total_gifts_since_2010 >= 10000;
Either one of two things will happen:
What I want it to do, which is only adds amounts after 2010.
Not what I want it to do, which is add all the amounts, but only
select/display the ones after 2010.
So my question would be something like this: Does the entire query happen instruction-by-instruction, or does the WHERE clause have an immediate effect on the query?
1) WHERE should precede GROUP BY (in the statement)
2) The sequence is following: JOIN - WHERE - GROUP BY - SELECT list
Related
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%.
---below query gives all the customers from fact irrespective of condition
SELECT count( dbo.Fact_Promotion.customerid) as Mailquantity
FROM dbo.Fact_Promotion
INNER JOIN dbo.Dim_Promotion
ON dbo.Fact_Promotion.PromotionID = dbo.Dim_Promotion.PromotionID
---below query gives customers with where condition
SELECT count(distinct fact_loan.customerid) as [New loans] ,avg(Fact_Loan.Financeamount) as [Avg New Loan Amount]
FROM dbo.Fact_Promotion
where <condition>
AND dbo.Fact_Loan.LoanTypeID = 6
AND dbo.Fact_Loan.AccountStatusID = 1
----below query gives customers with different where condition
SELECT count(distinct fact_loan.customerid) as [Total loans],avg(Fact_Loan.Financeamount) as [Avg Total Loan Amount]
FROM dbo.Fact_Promotion
where <condition>
AND dbo.Fact_Loan.AccountStatusID = 1
I'm not sure from your question what you are trying to achieve.
The WHERE clause in the second query appears to deliver a subset of the data from the WHERE clause in the third query. Both WHERE statements look identical with the exception that the second query (New loans) includes an extra condition that the LoanTypeId (presumably the financial product they have taken) is 6. I guess this is the latest loan product or campaign.
Without knowing what you're trying to do it's difficult to give you an answer but if you want to show total number of customers by LoanTypeId you could aggregate a count by adding the LoanTypeId column to the SELECT statement and adding a GROUP BY dbo.Fact_Loan.LoanTypeId to the end of the statement.
This may not be a straight forward as that as you're doing some other stuff in your SELECT (such as the DISTINCT and the AVG) but without knowing what your end goal is, it's difficult to fully answer your question.
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.
This an MS Access related question.
I get the Collateral divided 50 times because I have 50 rows in my ExchangeRates table... however the SELECT statement is supposed to only extract the value associated to CurrencyCode="EUR". How can I change the below statement to have the division being applied once only?
SELECT tbl_A.Security, tbl_A.Typ, Sum(([Collateral]/(SELECT tblExchangeRates.RateToUSD
FROM tblExchangeRates
WHERE (((tblExchangeRates.CurrencyCode)="EUR"))))) AS CollateralUSD
FROM tbl_A, tblExchangeRates
GROUP BY tbl_A.Security, tbl_A.Typ
HAVING (((tbl_A.Typ)="PR"));
It looks like this is what I was willing to get, just an Alias. SQL gurus, you are welcome to review.
SELECT tbl_A.Security, Sum(([Collateral]/[RateToUSD])) AS CollateralUSD
FROM tbl_A, (SELECT RateToUSD
FROM tblExchangeRates
WHERE CurrencyCode = 'EUR') AS MyAliasQ
GROUP BY tbl_A.Security
HAVING (((tbl_A.Typ)="PR"));
I have seen some close answers and I have been trying to adapt them to Access 2013, but I can't seem to get it to work. I have two queries:
First query returns
original_staff_data
Month
Year
staff_uid
staff_abbrev
employee_name
staff_salary
It pulls this from tables staff, and salary_by_month and employee_name and number_of_days_at_spec_building (this records where they check in when they work)
transaction_data_by_staff.total
Month
Year
staff_uid
total_revenue
totat_profit
this also pulls information from staff, but sums up over multiple dates in a transaction table creating a cumulative value for each staff_uid so I can't combine the two queries directly.
My problem is I want to create a query that brings results from both. However, not all staff members in Q1 will be in Q2 every day/week/month (vacations, etc) and since I want to ultimately create a final results:
Final_Result
Month
Year
staff_uid
staff_abbrev
employee_name
staff_salary
total_revenue
total_profit
The SQL:
SELECT
original_staff_data.*
, transaction_data_by_staff.total_rev
, transaction_data_by_staff.total_profit
FROM transaction_data_by_staff
RIGHT JOIN original_staff_data
ON (
transaction_data_by_staff.year = original_staff_data.year
AND transaction_data_by_staff.month = original_staff_data.month
) WHERE transaction_data_by_staff.[staff_uid] = [original_staff_data].[staff_uid];
I would like it if there is no revenue or profit that month from that employee, it makes those values 0. I have tried join (specifically RIGHT join with Q1 as the RIGHT join) and it doesn't seem to work, I still only get the subset. There are originally in the original_staff_data query 750 entries so therefore there should be in the final query 750 entries, I am only getting 252, which is the total in transaction_data_by_staff. Any clue on how the ACCESS 2013 SQL should look?
Thanks
Jon
Move the link by stuff_uid to the ON clause, like this:
SELECT original_staff_data.*, transaction_data_by_staff.total_rev, transaction_data_by_staff.total_profit
FROM transaction_data_by_staff RIGHT JOIN original_staff_data ON (transaction_data_by_staff.year = original_staff_data.year) AND (transaction_data_by_staff.month = original_staff_data.month)
AND (((transaction_data_by_staff.[staff_uid])=[original_staff_data].[staff_uid]));