Date problem in MYSQL Query - sql

Am looking for a query to sum values in a particular time duration say an year or a particular month in an year using MySQL syntax. Note that my transaction_date column stores daily amount transacted.
Am example of a query that returns total sales in an year query would look something like this
SELECT SUM(transaction_amount) WHERE transaction_date = (YEAR)
Am example of a query that returns total sales in an particular month and year would look something like this
SELECT SUM(transaction_amount) WHERE transaction_date = (YEAR)(MONTH)
How achievable is this?

SELECT SUM(transaction_amount)
WHERE YEAR(transaction_date) = '2008'
GROUP BY YEAR(transaction_date)
The second line may not be needed, depending on what you want exactly.

Related

How to write SQL statement to select for data broken up for each month of the year?

I am looking for a way to write an SQL statement that selects data for each month of the year, separately.
In the SQL statement below, I am trying to count the number of instances in the TOTAL_PRECIP_IN and TOTAL_SNOWFALL_IN columns when either column is greater than 0. In my data table, I have information for those two columns ("TOTAL_PRECIP_IN" and "TOTAL_SNOWFALL_IN") for each day of the year (365 total entries).
I want to break up my data by each calendar month, but am not sure of the best way to do this. In the statement below, I am using a UNION statement to break up the months of January and February. If I keep using UNION statements for the remaining months of the year, I can get the answer I am looking for. However, using 11 different UNION statements cannot be the optimal solution.
Can anyone give me a suggestion how I can edit my SQL statement to measure from the first day of the month, to the last day of the month for every month of the year?
select monthname(OBSERVATION_DATE) as "Month", sum(case when TOTAL_PRECIP_IN or TOTAL_SNOWFALL_IN > 0 then 1 else 0 end) AS "Days of Rain" from EMP_BASIC
where OBSERVATION_DATE between '2019-01-01' and '2019-01-31'
and CITY = 'Olympia'
group by "Month"
UNION
select monthname(OBSERVATION_DATE) as "Month", sum(case when TOTAL_PRECIP_IN or TOTAL_SNOWFALL_IN > 0 then 1 else 0 end) from EMP_BASIC
where OBSERVATION_DATE between '2019-02-01' and '2019-02-28'
and CITY = 'Olympia'
group by "Month"```
Your table structure is too unclear to tell you the exact query you will need. But a general easy idea is to build the sum of your value and then group by monthname and/or by month. Sice you wrote you only want sum values greater 0, you can just put this condition in the where clause. So your query will be something like this:
SELECT MONTHNAME(yourdate) AS month,
MONTH(yourdate) AS monthnr,
SUM(yourvalue) AS yoursum
FROM yourtable
WHERE yourvalue > 0
GROUP BY MONTHNAME(yourdate), MONTH(yourdate)
ORDER BY MONTH(yourdate);
I created an example here: db<>fiddle
You might need to modify this general construct for your concrete purpose (maybe take care of different years, of NULL values etc.). And note this is an example for a MYSQL DB because you wrote about MONTHNAME() which is in most cases used in MYSQL databases. If you are using another DB type, maybe you need to do some modifications. To make sure that answers match your DB type, tag it in your question, please.

SQL Server query date and amount

I am trying to create an SQL query which is based on the following info.
I have an amount bought and sold for each day for articles. I am trying to have a query that shows:
Total "amount" per "article" per "month
"amount" should be split into "positive total" and "negative total", summing up all positive "amount" and all negative "amount" separately.
THe date has the format "yyyy-mm-dd 00:00:00.000"
I tried the following
SELECT article, date, SUM (amount) Total FROM shop group by FORMAT(date, 'yyyy_MM'), article
I get the following message
"date is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause"
If I take the date out of the query everything works fine and it calculates the totals.
You need a so-called injective function for your dates: way to convert all dates in a month to the same value, and you need to use it both in your SELECT and GROUP BY clauses. LAST_DAY() is a decent function to use. So is DATE_FORMAT(date, '%Y-%m'), by the way.
Try this:
SELECT article, LAST_DAY(date) month_ending, SUM (amount) Total
FROM shop
GROUP BY LAST_DAY(date), article
There's a general writeup of solutions to this problem here.
Original answer for MySQL
There are mainly two mistakes in your query:
FORMAT is a function that converts a number to a string. So, MySQL will convert your date to a number first (which should not even be possible and raise an error, but MySQL does convert it to some number nonetheless) and then make sense of the format 'yyyy_MM', maybe taking MM to mean Myanmar, I don't know. I assume you get a different value for each day, instead of one value per month. You want DATE_FORMAT(date, '%Y-%m') instead.
You try to group by month, but then you display the date. Which date? A month has up to 31 different dates. You must display the month you grouped by instead (i.e. again DATE_FORMAT(date, '%Y-%m')).
As to separating positive and negative amounts, you can use conditional aggrgation, i.e. CASE WHEN inside the aggregation function (SUM).
SELECT
DATE_FORMAT(date, '%Y-%m') AS month,
article,
SUM(CASE WHEN amount > 0 THEN amount ELSE 0 END) AS positive_total,
SUM(CASE WHEN amount < 0 THEN amount ELSE 0 END) AS negative_total
FROM shop
GROUP BY DATE_FORMAT(date, '%Y-%m'), article
ORDER BY DATE_FORMAT(date, '%Y-%m'), article;
Updated answer for SQL Server
In SQL Server FORMAT(date, 'yyyy_MM') is a function to get the year and month from a date. The query is hence:
SELECT
FORMAT(date, 'yyyy_MM') AS month,
article,
SUM(CASE WHEN amount > 0 THEN amount ELSE 0 END) AS positive_total,
SUM(CASE WHEN amount < 0 THEN amount ELSE 0 END) AS negative_total
FROM shop
GROUP BY FORMAT(date, 'yyyy_MM'), article
ORDER BY FORMAT(date, 'yyyy_MM'), article;

Is there a way to limit a sum up to a calculated date in a table?

I have a table with SentDate and RefundAmounts. I would like to sum up the amounts on each row from the date until a year into the future for every line.
In the example below I would like to add a column that says sum for the year.
This sum should be for the first line the sum of refunds from '2006-12-14' until '2007-12-14' which would be 3696,22 as there were no refunds during that period.
The second row would be from '2007-12-24' until '2008-12-24' which would be 463,05
SentDate YearAhead RefundAmount
2006-12-14 2007-12-14 3696,22
2007-12-24 2008-12-24 394,35
2008-12-18 2009-12-18 44,33
2008-12-19 2009-12-19 24,37
2009-12-16 2010-12-16 21,88
I have tried something along the lines of
select SentDate, dateadd(year,1,sentdate) YearAhead, SumRefund
from table
but I have no idea how to get the annual future sum for each row
Thanks for the suggestion. The final result should look as follows:
SentDate YearAhead RefundAmount SumForYear
2006/12/14 2007/12/14 3696,22 3696,22
2007/12/24 2008/12/24 394,35 463,05
2008/12/18 2009/12/18 44,33 90,58
2008/12/19 2009/12/19 24,37 46,25
2009/12/16 2010/12/16 21,88 21,88
You need to join with a BETWEEN to gather all rows that compose that period, then use GROUP BY with SUM to the result.
select
T.SentDate,
dateadd(year, 1, T.SentDate) YearAhead,
SUM(P.SumRefund) AS TotalOverYear
from
YourTable AS T
INNER JOIN YourTable AS P ON P.SentDate BETWEEN T.SendDate AND DATEADD(YEAR, 1, T.SendDate)
GROUP BY
T.SentDate
Something like this should suite your needs if you always need a complete year:
select sum(refund) as refundAmounts,year(min(SentDate)) as year from yourTable group by year(SentDate)
the year function gets only the year part from a datetime row and with group by you can split the aggregation of sum and min function to different groups.

show no of hours each week for specific project id sql

I have table like this:
Now I want to see sum of hour for each week for each project .How can i query that.
I tried with query
select CurrentData.STATUS,
sum(CurrentData.HOURS), CurrentData.WEEKS
from CURRENT_DATA CurrentData
group by currentData.HOURS, CurrentData.STATUS, CurrentData.WEEKS, CurrentData.PROJECT_ID
having currentData.WEEKS = CurrentData.WEEKS
order by CurrentData.WEEKS;
But still each week coming as separate rows.Not sure how to do it
Do not use HOURS in group by. The are in the group function SUM:
SELECT PROJECT_ID, STATUS, YEARS, WEEKS, SUM (CurrentData.HOURS)
FROM CURRENT_DATA
GROUP BY PROJECT_ID, STATUS, Years, WEEKS
ORDER BY Years, WEEKS
And what is in the having clause. That is always true. Do you want a certain week and year? And you can get rid of "CurrentData.". You have only one table and you don't need alias for this table.
Here filtered for year 2016 and summed for all project id :
SELECT STATUS, WEEKS, SUM (CurrentData.HOURS)
FROM CURRENT_DATA
WHERE Years = 2016
GROUP BY STATUS, WEEKS
ORDER BY WEEKS

T-SQL average calculation

I want to incorporate two average calculations for a bunch of value columns in my select statement.
see this link for my simplified table structure including the desired output calculation: Pastebin
1) moving average:
Month1 = value of the value1-column for that month, Month2 = if sum == 0 then write 0, else avg(Month1 and Month2) and so on.
So for each product, I want the moving average for each month within one year.
I have this set up in my Excel but I can't transfer the expression to sql.
2) overall average:
for each product, calculate the average over all years and duplicate the calculated value to all rows for that product.
I hope you can help me out with this. It looks like I need a procedure but maybe it is just a simple statement.
SQL-Server 2012 supports the analytic functions required to do this:
SELECT Product,
Month,
Year,
Value,
AVG_YTD = AVG(Value) OVER(PARTITION BY Year ORDER BY Month),
AVG_Year = AVG(Value) OVER(PARTITION BY Product, Year),
AVG_Overall = AVG(Value) OVER(PARTITION BY Product)
FROM T;
Simplified Example on SQL Fiddle