Grouping all dates as one field and showing the sum of sales - sql

I have converted all dates within my table to reflect as YYYY/MM/01 but I am left with 25 or so of these dates that are all the same and I just want to group them together and I can't figure out how to do it. I'm newish to SQL and was hoping someone could point me in the right direction for this.
Much appreciated!
SELECT
DATEFROMPARTS(YEAR(ReportedDate), MONTH(ReportedDate), 1) AS Date, SUM(Sales) Sales
FROM
dbo.Sales
WHERE
YEAR(ReportedDate) = 2018 AND MONTH(ReportedDate) = 01
GROUP BY
ReportedDate

Because you are grouping by ReportedDate, for every ReportedDate you will get a record, even though you didn't select ReportedDate in your SELECT clause. Think of it as a hidden column in your data. Instead, try grouping by the functions in your select statement.
SELECT
DATEFROMPARTS(YEAR(ReportedDate), MONTH(ReportedDate), 1) AS Date, SUM(Sales) Sales
FROM
dbo.Sales
WHERE
YEAR(ReportedDate) = 2018 AND MONTH(ReportedDate) = 01
GROUP BY
DATEFROMPARTS(YEAR(ReportedDate), MONTH(ReportedDate), 1)

As an alternative to your query I suggest you to use EOMONTH function. You would not need to use extra date functions. And I think it's better to show last day of month than first day when showing totals per month
SELECT
EOMONTH(ReportedDate) AS Date, SUM(Sales) Sales
FROM
dbo.Sales
WHERE
EOMONTH(ReportedDate) = EOMONTH(GETDATE(), -1)
GROUP BY
EOMONTH(ReportedDate)
Notes:
EOMONTH(GETDATE(), -1) gets last day of previous month
Use DATEADD(DD, 1, EOMONTH(ReportedDate, -1)) to get first day of month

Related

Matching date with calculated DATEADD date

I am trying to create a table with columns containing the current date, prior year date, and additional column for the total sum revenue as below:
cur_date | py_date | py_rev
I'm trying to compare revenue across any daily period across years. Assume all dates and revenue values are included in the same SQL Server table.
I attempted to use a case statement using [date] = DATEADD(wk,-52,[date]) as the condition to return the appropriate total. The full line code is below:
select
[date] as cur_date,
DATEADD(wk,-52,[date]) py_date,
SUM(case when [date] = DATEADD(wk,-52,[date]) then sum_rev else 0 end) as py_rev
from summary
group by [date]
When running this code the py_date is as expected but py_rev returns 0 as if there is no match. What's most confusing is if I hard code a random date in place of the DATEADD portion then a total is returned. I have also tried CAST to format both date and the DATEADD portion as date with no luck.
Is there something about DATEADD that will not match to other date columns that I'm missing?
If you want the previous years revenue, then lag() is one method. This works assuming that "previous year" means 52 weeks ago and you have records for all dates:
select [date] as cur_date,
dateadd(week, -52, [date]) as py_date,
lag(sum_rev, 52 * 7) over (order by date) as py_rev
from summary;
If you do not have records for all dates, then another approach is needed. You can use a LEFT JOIN:
select s.date, dateadd(week, -52, s.[date]),
sprev.sum_rev as py_rev
from summary s left join
summary sprev
on sprev.date = dateadd(week, -52, s.[date]);

SQL : Get last 3 month data (with only available data in the column), not from current month or today?

Anyone help me out on this scenario. I need to get a last 3 month data from particular column, which is not from current date but only from available date.
Ex :
I have one Table named Shop and column named OrderDate, In OrderDate i have only dates until 30-06-2017, but today's date is 07-02-2018. From this i need to get last 3 months data, which is Jun'17, May'17 and Apr'17.
If data available in till July'17 means i need result Jul'17,Jun'17 & May'17. And so on.
Any can help on this to achieve in SQL ?
Thanks in advance.
I assume that column OrderDate is of date or datetime datatype.
select * from Shop
where OrderDate >
(select dateadd(month, -3, max(OrderDate)) from Shop)
I think the easiest way to get this is to select the largest date in that table and use that to create the filter.
So;
Select *
from table
where date >
Dateadd
('m', -3,
( Select Max (date) from table)
)
Apologies in advance for poor formatting
You will have to find the maximum date in the table and use that:
select s.*
from Shop s,
(select convert(date,
format(
dateadd(MONTH, -3, max(OrderDate)), 'yyyyMM01')
,112) as fromDate from Shop) md
where s.OrderDate >= md.fromDate

How do I correctly use the SQL Sum function with multiple variables and grouping?

I am trying to write an SQL statement based on the following code.
CREATE TABLE mytable (
year INTEGER,
month INTEGER,
day INTEGER,
hoursWorked INTEGER )
Assuming that each employee works multiple days over each month in a 3 year period.
I need to write an sql statement that returns the total hours worked in each month, grouped by earliest year/month first.
I tried doing this, but I don't think it is correct:
SELECT Sum(hoursWorked) FROM mytable
ORDER BY(year,month)
GROUP BY(month);
I am a little confused about how to operate the sum function in conjunction with thee GROUP BY or ORDER BY function. How does one go about doing this?
Try this:
SELECT year, month, SUM(hoursWorked)
FROM mytable
GROUP BY year, month
ORDER BY year, month
This way you will have for example:
2014 December 30
2015 January 12
2015 February 40
Fields you want to group by always have be present in SELECT part of query. And vice-versa - what you put in SELECT part, need be also in GROUP BY.
SELECT year, month, Sum(hoursWorked)as workedhours
FROM mytable
GROUP BY year,month
ORDER BY year,month;
You have to group by year and month.
Is this what you are trying to do. This will sum by Year/Month and Order by Year/Month.
Select [Year], [Month], Sum(HoursWorked) as WorkedHours
From mytable
Group By [Year], [Month]
Order by [Year], [Month]
You have to group by year and month, otherwise you will have the hours you worked on March 2014 and 2015 in one record :)
SELECT Sum(hoursWorked) as hoursWorked, year, month
FROM mytable
GROUP BY(year, month)
ORDER BY(year,month)
;

Fiscal Year To-Date in Where Clause (T-SQL)

Company's Fiscal Year: July 1 - June 30
I have a query where I am trying to capture aggregate # of units and $ revenue by product and cost center for the fiscal year-to-date. It will run on the 1st of the month and look through the last day of the previous month. Fiscal year does not appear in the report - it is criteria.
Mix of pseudocode and SQL:
Where
If datepart(mm,getdate()) - 1 < 7
THEN
transaction_post_date BETWEEN 7/1/ previous year AND dateadd(day,-(day(getdate()),getdate())
Else
transaction_post_date BETWEEN 7/1/current year AND dateadd(day,-(day(getdate()),getdate())
Am I on the write track? How do I write the SQL for a specific date on a year that depends on SQL - 7/1/current year?
I am weak using variables and do not even know if I have access to create them on the SQL Server DB, which is rather locked down. Definitely can't create a function. (I'm a business analyst.)
UPDATE, Fiscal year goes forward, so July 1, 2010, is Fiscal Year 2011.
I think this works:
Year(dateadd(month,6,htx.tx_post_date)) = Year(DateAdd(Month, 5, GetDate()))
Feeback?
And now I've been asked to add Fiscal Year-To-Date fields for quantity and revenue to the following query which gave me totals for
Select
inv.ITEM_CODE
, inventory.ITEM_NAME
, cc.COST_CENTER_CODE
, tx.REV_CODE_ID
, tx.PRICE
, tx.ITEM_SALE_ID
, sum(tx.quantity)
, sum(tx.amount)
from
transactions tx
inner join inventory inv on inv.item_id = tx.item_id
left outer join cost_center cc on cc.cost_center_id = tx.cost_center_id
where
DATEPART(mm, tx.tx_date) = DATEPART(mm,dateadd(m,-1,getdate()))
and DATEPART(yyyy, tx.tx_date) = DATEPART(yyyy,dateadd(m,-1,getdate()))
group by
inv.ITEM_CODE
, inventory.ITEM_NAME
, cc.COST_CENTER_CODE
, tx.REV_CODE_ID
, tx.PRICE
, tx.ITEM_SALE_ID
I need to add the fiscal year-to-date quantity and and amount columns to this report. Would a correlated subquery by the way to go? Would the joins be tricky? I've never used a subquery with an aggregation/grouping query.
Thanks for all the previous help.
Here is how I would do it if I needed to group by Fiscal Year:
Group by Year(DateAdd(Month, -6, TransactionDate))
May be not exactly it, but you get the idea.
I would add a calculated column to your table called FiscalYear (with the proper calculation) and select based on that column
I believe the easiest way is to do this in two steps. Use the WHERE Clause to filter your YTD and then a GROUP BY to group by FY. Since your FY begins in July(7) then increment the FY if the month is greater than June(6).
WHERE CLAUSE:
WHERE
DATEDIFF(DAY, transaction_post_date, Cast(Month(GetDate()) as varchar) +
'/' + Cast(Day(GetDate()) as varchar) + '/' + CAST(Case WHEN
MONTH(transaction_post_date) > 6 then YEAR(transaction_post_date) + 1 else
Year(transaction_post_date) end as varchar)) >=0
GROUP BY CLAUSE:
GROUP BY CASE WHEN MONTH(transaction_post_date) > 6 then
Year(transaction_post_date) + 1 else YEAR(transaction_post_date) end

Return just the last day of each month with SQL

I have a table that contains multiple records for each day of the month, over a number of years. Can someone help me out in writing a query that will only return the last day of each month.
SQL Server (other DBMS will work the same or very similarly):
SELECT
*
FROM
YourTable
WHERE
DateField IN (
SELECT MAX(DateField)
FROM YourTable
GROUP BY MONTH(DateField), YEAR(DateField)
)
An index on DateField is helpful here.
PS: If your DateField contains time values, the above will give you the very last record of every month, not the last day's worth of records. In this case use a method to reduce a datetime to its date value before doing the comparison, for example this one.
The easiest way I could find to identify if a date field in the table is the end of the month, is simply adding one day and checking if that day is 1.
where DAY(DATEADD(day, 1, AsOfDate)) = 1
If you use that as your condition (assuming AsOfDate is the date field you are looking for), then it will only returns records where AsOfDate is the last day of the month.
Use the EOMONTH() function if it's available to you (E.g. SQL Server). It returns the last date in a month given a date.
select distinct
Date
from DateTable
Where Date = EOMONTH(Date)
Or, you can use some date math.
select distinct
Date
from DateTable
where Date = DATEADD(MONTH, DATEDIFF(MONTH, -1, Date)-1, -1)
In SQL Server, this is how I usually get to the last day of the month relative to an arbitrary point in time:
select dateadd(day,-day(dateadd(month,1,current_timestamp)) , dateadd(month,1,current_timestamp) )
In a nutshell:
From your reference point-in-time,
Add 1 month,
Then, from the resulting value, subtract its day-of-the-month in days.
Voila! You've the the last day of the month containing your reference point in time.
Getting the 1st day of the month is simpler:
select dateadd(day,-(day(current_timestamp)-1),current_timestamp)
From your reference point-in-time,
subtract (in days), 1 less than the current day-of-the-month component.
Stripping off/normalizing the extraneous time component is left as an exercise for the reader.
A simple way to get the last day of month is to get the first day of the next month and subtract 1.
This should work on Oracle DB
select distinct last_day(trunc(sysdate - rownum)) dt
from dual
connect by rownum < 430
order by 1
I did the following and it worked out great. I also wanted the Maximum Date for the Current Month. Here is what I my output is. Notice the last date for July which is 24th. I pulled it on 7/24/2017, hence the result
Year Month KPI_Date
2017 4 2017-04-28
2017 5 2017-05-31
2017 6 2017-06-30
2017 7 2017-07-24
SELECT B.Year ,
B.Month ,
MAX(DateField) KPI_Date
FROM Table A
INNER JOIN ( SELECT DISTINCT
YEAR(EOMONTH(DateField)) year ,
MONTH(EOMONTH(DateField)) month
FROM Table
) B ON YEAR(A.DateField) = B.year
AND MONTH(A.DateField) = B.Month
GROUP BY B.Year ,
B.Month
SELECT * FROM YourTableName WHERE anyfilter
AND "DATE" IN (SELECT MAX(NameofDATE_Column) FROM YourTableName WHERE
anyfilter GROUP BY
TO_CHAR(NameofDATE_Column,'MONTH'),TO_CHAR(NameofDATE_Column,'YYYY'));
Note: this answer does apply for Oracle DB
Here's how I just solved this. day_date is the date field, calendar is the table that holds the dates.
SELECT cast(datepart(year, day_date) AS VARCHAR)
+ '-'
+ cast(datepart(month, day_date) AS VARCHAR)
+ '-'
+ cast(max(DATEPART(day, day_date)) AS VARCHAR) 'DATE'
FROM calendar
GROUP BY datepart(year, day_date)
,datepart(month, day_date)
ORDER BY 1