Using DATEPART function in access SQL query with joined tables and aggregate function - sql

I want to select the year and quarter parts of the date in a table rather than the whole date. I built the following query to achieve this:
SELECT Clients.ClientID,
Sum(AccountVals.ValuationAmount) AS SumOfValuationAmount,
Datepart("YYYY", AccountVals.valuationAmount) AS valYear,
Datepart("Q", AccountVals.valuationAmount) AS valQuarter
FROM (Accounts
INNER JOIN Clients
ON Accounts.ClientID = Clients.ClientID)
INNER JOIN AccountVals
ON Accounts.AccountID = AccountVals.AccountID
GROUP BY Clients.ClientID,
SumOfValuationAmount,
valYear,
valQuarter;
Although I have successfully used DATEPART in a simple select query the fact that this query is both an aggregate function and have linked tables is throwing me. Any ideas?
EDIT: I realise my query doesn't have any criteria which means it could be trying to aggregate the result from different dates so it can't show the dateparts. I tried adding something like HAVING valYear = 2012 AND valQuarter = 3 but get the same error

I don't think you can use an alias in the group by clause, at least not without a subquery. One solution is to repeat the exact expression in the group by, f.e.:
group by
Clients.ClientID
, datepart("YYYY", AccountVals.valuationAmount)
, datepart("Q", AccountVals.valuationAmount)

Related

Grouping and Summing in SQL

Good day
I would like to find out how I would Sort and group the following data by grouping the Account and summing the grandTotal of the Account per Month.
This is my current Select statement:
SELECT
tbl_AccountLedger.ledgerName
,tbl_SalesMaster.date
, tbl_SalesMaster.grandTotal
FROM tbl_SalesMaster
INNER JOIN tbl_AccountLedger ON tbl_SalesMaster.ledgerId =tbl_AccountLedger.ledgerId
Here is wat my select statement is bringing back
Now I need to sort this data by summing the grand total for each month for a legerName
You can use the below query on SQL 2012 or higher version. I will suggest please read grouping in SQL.
SELECT
tbl_AccountLedger.ledgerName
,DATEFROMPARTS(YEAR(tbl_SalesMaster.date),MONTH(tbl_SalesMaster.date),1) AS Month
, SUM(tbl_SalesMaster.grandTotal) AS TotalGrandTotal
FROM tbl_SalesMaster
INNER JOIN tbl_AccountLedger ON tbl_SalesMaster.ledgerId =tbl_AccountLedger.ledgerId
GROUP BY tbl_AccountLedger.ledgerName, DATEFROMPARTS(YEAR(tbl_SalesMaster.date),MONTH(tbl_SalesMaster.date),1)

Group by Month and Year in SQL

I am trying to make a query, I must receive a date and give a report in which I must show the sum of the amounts at the end of a month.
What I have so far is this:
CREATE PROCEDURE consulta
#fecha DATE
AS
SELECT
SUM(dca.UNIDADES) as Amount,
MONTH(ca.FINICIO) as Month,
YEAR(ca.FINICIO)
FROM
DETALLE_CONTRATO_ALQUILER dca
INNER JOIN
CONTRATOALQUILER ca ON dca.CODCONTRATO = ca.CODCONTRATO
AND ca.FINICIO >= #fecha
AND YEAR(ca.FINICIO) = YEAR(#fecha)
GROUP BY
MONTH(ca.FINICIO), YEAR(ca.FINICIO)
HAVING
SUM(dca.UNIDADES) > 2;
The comparison of years is because I only have to obtain the months of that same year.
I also attach my diagram:
The context of the database is about product rentals, the tables I use are the rental contract and the detail
I know I get errors because when I enter a specific date, I do not get results. I do not know what I'm failing. My query is correctly logical?
What I expect to obtain is:
Amount | Month | Year
12 1 2017
45 2 2017
...
Here's the example
I would assume all rows of both tables have matching row(s) in the other table, so an INNER JOIN is what you need.
There's a small detail in your query that smells fishy. Your join includes filtering conditions that may throw rows out of the query. Maybe you should place the filtering conditions in a WHERE clause instead of a JOIN clause, as in:
SELECT
SUM(dca.UNIDADES) as Amount,
MONTH(ca.FINICIO) as Month,
YEAR(ca.FINICIO)
FROM
DETALLE_CONTRATO_ALQUILER dca
INNER JOIN
CONTRATOALQUILER ca ON dca.CODCONTRATO = ca.CODCONTRATO
WHERE ca.FINICIO >= #fecha -- Using WHERE instead of JOIN here!
AND YEAR(ca.FINICIO) = YEAR(#fecha)
GROUP BY
MONTH(ca.FINICIO), YEAR(ca.FINICIO)
HAVING
SUM(dca.UNIDADES) > 2;
You can place filtering in the JOIN clause and that is very useful for OUTER JOINs. However, for INNER JOINs that applies to the join itself and may filter out rows you wanted to include.

Cannot Group by Year

Beginner SQL Question:
I'm trying to do a group by, by year and I'm getting funny results. I am using SQL Server 2008.
First, I tried
select count(applicationkey) , approveddate from ida.applications group by approveddate
To get a count of applications by date. However, I am interested in applications by year in stead of day so I tried
select count(applicationkey) , approveddate from ida.applications group by year(approveddate)
When I do this, I get an error message -Column 'ida.applications.ApprovedDate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.-
However, if I do this I get results
select count(applicationkey) from ida.applications group by year(approveddate)
I get results. Its just I want to be able to see what year matches to which count, which I cannot do for some reason. Does anyone know why I am having this problem?
select count(applicationkey),
year(approveddate)
from ida.applications
group by year(approveddate)
group by must match fields in select if not using an aggregate.
You have all the correct parts there, just include the year(approveddate) in your select like so
select count(applicationkey), year(approveddate)
from ida.applications
group by year(approveddate)
In a group query, columns selected have to be aggregate functions or appear in the group-by list, because otherwise SQL wouldn't know which of the multiple values for the column in the group to use.
You can fix your query easily by using
select count(applicationkey) , year(approveddate)
from ida.applications group by year(approveddate)
-- the year displayed is from the group by list

How can I combine these two query from the same table?

Since "ColdFusion does not support joins through INNER JOIN or OUTER JOIN clauses"
How would I be able to combine these two queries, where they give me data from
the past 2 months?
select starburst_dept_name, starburst_dept_average,MONTHLY_PAST_DATE
from cse_reports_month
where starburst_dept_name is not NULL
and YEAR(MONTHLY_PAST_DATE) = YEAR(GETDATE())
and MONTH(MONTHLY_PAST_DATE) = MONTH(GETDATE())-1
select starburst_dept_name, starburst_dept_average,MONTHLY_PAST_DATE
from cse_reports_month
where starburst_dept_name is not NULL
and YEAR(MONTHLY_PAST_DATE) = YEAR(GETDATE())
and MONTH(MONTHLY_PAST_DATE) = MONTH(GETDATE())-2
I would like a query to combine these two how would I do this so it would
work in ColdFusion?
What I would like to to is compare the starburst_dept_average last month > starburst_dept_average last 2 month ago?
Just to clarify, CF does not support INNER AND OUTER JOINs only in a query of a query (QoQ). Is cse_reports_month the name of a query or the name of a database table? Your use of getdate() makes it sound like this is a regular SQL query, not a QoQ.
The following query should work according to your original logic:
SELECT starburst_dept_name, starburst_dept_average, MONTHLY_PAST_DATE
FROM cse_reports_month
WHERE starburst_dept_name is not NULL
AND YEAR(MONTHLY_PAST_DATE) = YEAR(GETDATE())
AND (
MONTH(MONTHLY_PAST_DATE) = MONTH(GETDATE())-1 OR
MONTH(MONTHLY_PAST_DATE) = MONTH(GETDATE())-2
)
But as was pointed out, this won't work for Jan. & Feb.- you'll need to use some different date comparison operators.
Depending on exactly what you are trying to show (and what the MONTHLY_PAST_DATE data represents), the following may work (you may need to modify a bit according your specific needs):
SELECT starburst_dept_name, starburst_dept_average, MONTHLY_PAST_DATE
FROM cse_reports_month
WHERE starburst_dept_name is not NULL
AND DATEDIFF(m,MONTHLY_PAST_DATE,getdate()) IN (1,2)
You can combine these query results by using the SQL UNION statement.
http://www.w3schools.com/sql/sql_union.asp

SQL: HAVING clause

See the following SQL statement:
SELECT datediff("d", MAX(invoice.date), Now) As Date_Diff
, MAX(invoice.date) AS max_invoice_date
, customer.number AS customer_number
FROM invoice
INNER JOIN customer
ON invoice.customer_number = customer.number
GROUP BY customer.number
If the the following was added:
HAVING datediff("d", MAX(invoice.date), Now) > 365
would this simply exclude rows with Date_Diff <= 365?
What should be the effect of the HAVING clause here?
EDIT: I am not experiencing what the answers here are saying. A copy of the mdb is at http://hotfile.com/dl/40641614/2353dfc/test.mdb.html (no macros or viruses). VISDATA.EXE is being used to execute the queries.
EDIT2: I think the problem might be VISDATA, because I am experiencing different results via DAO.
As already pointed out, yes, that is the effect. For completeness, 'HAVING' is like 'WHERE', but for the already aggregated (grouped) values (such as, MAX in this case, or SUM, or COUNT, or any of the other aggregate functions).
Yes, it would exclude those rows.
Yes, that is what it would do.
WHERE applies to all of the individual rows, so WHERE MAX(...) would match all rows.
HAVING is like WHERE, but within the current group. That means you can do things like HAVING count(*) > 1, which will only show groups with more than one result.
So to answer your question, it would only include rows where the record in the group that has the highest (MAX) date is greater than 365. In this case you are also selecting MAX(date), so yes, it excludes rows with date_diff <= 365.
However, you could select MIN(date) and see the minimum date in all the groups that have a maximum date of greater than 365. In this case it would not exclude "rows" with date_diff <= 365, but rather groups with max(date_diff) <= 365.
Hopefully it's not too confusing...
You may be trying the wrong thing with your MAX. By MAXing the invoice.date column you are effectively looking for the most recent invoice associated with the customer. So effectively the HAVING condition is selecting all those customers who have not had any invoices within the last 365 days.
Is this what you are trying to do? Or are you actually trying to get all customers who have at least one invoice from more than a year ago? If that is the case, then you should put the MAX outside the datediff function.
That depends on whether you mean rows in the table or rows in the result. The having clause filters the result after grouping, so it would elliminate customers, not invoices.
If you want to filter out the new invoices rather than the customers with new invoices, you should use where instead so that you filter before grouping:
select
datediff("d",
max(invoice.date), Now) As Date_Diff,
max(invoice.date) as max_invoice_date,
customer.number
from
invoice
inner join customer on invoice.customer_number = customer.number
where
datediff("d", invoice.date, Now) > 365
group by
customer.number
I wouldn't use a GROUP BY query at all. Using standard Jet SQL:
SELECT Customer.Number
FROM [SELECT DISTINCT Invoice.Customer_Number
FROM Invoice
WHERE (((Invoice.[Date])>Date()-365));]. AS Invoices
RIGHT JOIN Customer ON Invoices.Customer_Number = Customer.Number
WHERE (((Invoices.Customer_Number) Is Null));
Using SQL92 compatibility mode:
SELECT Customer.Number
FROM (SELECT DISTINCT Invoice.Customer_Number
FROM Invoice
WHERE (((Invoice.[Date])>Date()-365));) AS Invoices
RIGHT JOIN Customer ON Invoices.Customer_Number = Customer.Number
WHERE (((Invoices.Customer_Number) Is Null));
The key here is to get a set of the customer numbers who've had an invoice in the last year, and then doing an OUTER JOIN on that result set to return only those not in the set of customers with invoices in the last year.