Group by date only on a Datetime column - sql

Having a table with a column like: mydate DATETIME ...
I have a query such as:
SELECT SUM(foo), mydate FROM a_table GROUP BY a_table.mydate;
This will group by the full datetime, including hours and minutes. I wish to make the group by, only by the date YYYY/MM/DD not by the YYYY/MM/DD/HH/mm.
How to do this?

Cast the datetime to a date, then GROUP BY using this syntax:
SELECT SUM(foo), DATE(mydate) FROM a_table GROUP BY DATE(a_table.mydate);
Or you can GROUP BY the alias as #orlandu63 suggested:
SELECT SUM(foo), DATE(mydate) DateOnly FROM a_table GROUP BY DateOnly;
Though I don't think it'll make any difference to performance, it is a little clearer.

I found that I needed to group by the month and year so neither of the above worked for me. Instead I used date_format
SELECT date
FROM blog
GROUP BY DATE_FORMAT(date, "%m-%y")
ORDER BY YEAR(date) DESC, MONTH(date) DESC

Or:
SELECT SUM(foo), DATE(mydate) mydate FROM a_table GROUP BY mydate;
More efficient (I think.) Because you don't have to cast mydate twice per row.

SELECT SUM(No), HOUR(dateofissue)
FROM tablename
WHERE dateofissue>='2011-07-30'
GROUP BY HOUR(dateofissue)
It will give the hour by sum from a particular day!

this worked for me
select
CONVERT(date, CONVERT(VARCHAR(10),sd.Date,112)) as Date,
sd.CodId as CodId,
p.Description ,
sum(sd.Quantity)as Quantity,
sum(sd.TotalQuantityXPriceWithIva) as TotalWithIva
from
SaleDetails sd
join Sales s on sd.SaleId = s.SaleId
join Products p on sd.ProductId = p.ProductId
Where
(
sd.Date >=' 1/1/2021 00:00:00'
and sd.Date <= '26/10/2021 23:59:59'
and p.BarCode = '7790628000034'
and ((s.VoucherTypeId >= 16 and s.VoucherTypeId <= 18)
or s.VoucherTypeId = 32 ))
group by
CONVERT(VARCHAR(10),sd.Date,112),
sd.CodId ,
p.Description
order by CONVERT(VARCHAR(10),sd.Date,112) desc

Related

SQL How can I get a count of messages going out by month

I have a table that sends out messages, I would like to get a total count of the messages that have been going out month by month over the last year . I am new to SQL so I am having trouble with it . I am using MSSQL 2012 this is my sql
SELECT sentDateTime, MessageID, status AS total, CONVERT(NVARCHAR(10), sentDateTime, 120) AS Month
FROM MessageTable
WHERE CAST(sentDateTime AS DATE) > '2017-04-01'
GROUP BY CONVERT(NVARCHAR(10), sentDateTime, 120), sentDateTime, MessageID, status
ORDER BY Month;
I think the month() and year() functions are more convenient than datepart() for this purpose.
I would go for:
select year(sentDateTime) as yr, month(sentDateTime) as mon, count(*)
from MessageTable
where sentDateTime > '2017-04-01'
group by year(sentDateTime), month(sentDateTime)
order by min(sentDateTime);
Additional notes:
Only include the columns in the select that you care about. This would be the ones that define the month and the count.
Only include the columns in the group by that you care about. Every combination of the expressions in the group by found in the data define a column.
There is no need to convert sentDateTime to a date explicitly for the comparison.
The order by orders the results by time. Using the min() is a nice convenience.
Including the year() makes sure you don't make a mistake -- say by including data from 2018-04 with 2017-04.
-- this selects the part of the date you are looking for, replace this with the date format you are using, this should give you what you are looking for
SELECT DATEPART(mm, GETDATE())
SELECT COUNT(DATEPART(mm, sentDateTime)), MessageID, status
From MessageTable where Cast(sentDateTime as date) > '2017-04-01'
group by DATEPART(mm, sentDateTime), MessageID, status
order by DATEPART(mm, sentDateTime)
You can group by the month number of the sentDateTime with the function DATEPART(MONTH, sentDateTime). The next select will also yield results if no message was sent for a particular month (total = 0).
;WITH PossibleMonths AS
(
SELECT
M.PossibleMonth
FROM
(VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) M(PossibleMonth)
),
MonthTotals AS
(
select
COUNT(1) AS Total,
DATEPART(MONTH, sentDateTime) [Month]
From
MessageTable
where
Cast(sentDateTime as date) > '2017-04-01'
group by
DATEPART(MONTH, sentDateTime)
)
SELECT
P.PossibleMonth,
Total = ISNULL(T.Total, 0)
FROM
PossibleMonths AS P
LEFT JOIN MonthTotals AS T ON P.PossibleMonth = T.Month

Get a count of a number of records with same create date

I have a table containing records all with a create date. I want to Select all the records created in January 2014 and have a count of how many were created each day. I've gotten as far as Selecting all the records created that month but I'm unsure how to proceed to get an output of all the days that month and a count of how many records were created.
SELECT TYPE
,PART_ID
,DESIRED_QTY
,RECEIVED_QTY
,CREATE_DATE
FROM WORK_ORDER
WHERE DATEPART(year,CREATE_DATE) = 2014 and DATEPART(month,CREATE_DATE) = 01
ORDER BY CREATE_DATE ASC
The information I'm selecting in that statement isn't important, it's just there in that query so I'm selecting something.
SELECT DATEPART(day,CREATE_DATE), count(*)
FROM WORK_ORDER
WHERE DATEPART(year,CREATE_DATE) = 2014 and DATEPART(month,CREATE_DATE) = 01
group by DATEPART(day,CREATE_DATE)
ORDER BY CREATE_DATE ASC
Is this what you are looking for? It is an aggregation query that does the count:
SELECT CAST(CREATE_DATE as Date) as date,
COUNT(*)
FROM WORK_ORDER
WHERE DATEPART(year, CREATE_DATE) = 2014 and DATEPART(month, CREATE_DATE) = 01
GROUP BY CAST(CREATE_DATE as Date)
ORDER BY CAST(CREATE_DATE as Date) ;
The CAST() is only needed if CREATE_DATE could have a time component. The reason this query uses CAST() is so the same structure will work on multiple months.
I want to add, that it is better to write the query like this:
SELECT CAST(CREATE_DATE as Date) as date, COUNT(*)
FROM WORK_ORDER
WHERE CREATE_DATE >= '2014-01-01' and CREATE_DATE < '2014-02-01'
GROUP BY CAST(CREATE_DATE as Date)
ORDER BY CAST(CREATE_DATE as Date) ;
The difference here is the WHERE clause. This formulation can make use of an index on CREATE_DATE. Your formulation has functions around the arguments, so it would not use the index.
If all you need is a count by day, I suggest:
SELECT COUNT(*)
FROM WORK_ORDER
WHERE DATEPART(year,CREATE_DATE) = 2014 and DATEPART(month,CREATE_DATE) = 01
GROUP BY DATEPART(DAY, CREATE_DATE)
SELECT
DATE(CREATE_DATE) as day,
COUNT(*) as count
FROM WORK_ORDER
WHERE DATEPART(year,CREATE_DATE) = 2014 and DATEPART(month,CREATE_DATE) = 01
GROUP BY DATE(CREATE_DATE)
SELECT DATEPART(year,CREATE_DATE),
DATEPART(month,CREATE_DATE),
DATEPART(day,CREATE_DATE),
count(*)
FROM WORK_ORDER
WHERE DATEPART(year,CREATE_DATE) = 2014
and DATEPART(month,CREATE_DATE) = 01
group by DATEPART(year,CREATE_DATE),
DATEPART(month,CREATE_DATE),
DATEPART(day,CREATE_DATE)
ORDER BY CREATE_DATE ASC

SQL query for MIN() of date in future

I need help with a query. I want to group a query by the ID field, and the MIN() of the date field. However, I want the min of all dates in the future.
Would I need a subquery here? The following will exclude all records that don't occur in the future.
SELECT CompanyCode, MIN(NextDate) AS NextFollowUpDate
FROM dbo.LeadNote AS LeadNote
GROUP BY CompanyCode
HAVING (MIN(NextDate) > GETDATE())
Just use a regular where:
SELECT CompanyCode, MIN(NextDate) AS NextFollowUpDate
FROM dbo.LeadNote AS LeadNote
WHERE NextDate > GETDATE()
GROUP BY CompanyCode
If you need every company code with nulls for missing items you can do this
SELECT cc.CompanyCode, g.NextFollowUpDate
FROM
(
SELECT DISTINCT CompanyCode
FROM dbo.LeadNote
) AS cc
LEFT JOIN
(
SELECT CompanyCode, MIN(NextDate) AS NextFollowUpDate
FROM dbo.LeadNote
WHERE NextDate > GETDATE()
GROUP BY CompanyCode
) AS g ON cc.CompanyCode = g.CompanyCode

Efficiently group by column aggregate

SELECT date, id, sum(revenue)
FROM table
WHERE date between '2013-01-01' and '2013-01-08'
GROUP BY date, id
HAVING sum(revenue)>1000
Returns rows that have revenue>1000.
SELECT date, id, sum(revenue)
FROM table
WHERE date between '2013-01-01' and '2013-01-08'
AND id IN (SELECT id FROM table where date between '2013-01-01' and '2013-01-08' GROUP BY id HAVING sum(revenue)>1000)
GROUP BY date, id
Returns rows for id's whose total revenue over the date period is >1000 as desired. But this query is much slower. Any quicker way to do this?
Make sure you have indexes on the date and id columns, and try this variation:
select t.date, t.id, sum(t.revenue)
from table t
inner join (
select id
from table
where date between '2013-01-01' and '2013-01-08'
group by id
having sum(revenue) > 1000
) ts on t.id = ts.id
where t.date between '2013-01-01' and '2013-01-08'
group by t.date, t.id
it's not MySQL, it's Vertica ;)
Cris, what projection and order by you using in CREATE TABLE ???
Do you try using database designer
see http://my.vertica.com/docs/6.1.x/HTML/index.htm#14415.htm

How do I get a maximium daily value of a numerical field over a year in SQL

How do I get a maximium daily value of a numerical field over a year in MS-SQL
This would query the daily maximum of value over 2008:
select
datepart(dayofyear,datecolumn)
, max(value)
from yourtable
where '2008-01-01' <= datecolumn and datecolumn < '2009-01-01'
group by datepart(dayofyear,datecolumn)
Or the daily maximum over each year:
select
datepart(year,datecolumn),
, datepart(dayofyear,datecolumn)
, max(value)
from yourtable
group by datepart(year,datecolumn), datepart(dayofyear,datecolumn)
Or the day(s) with the highest value in a year:
select
Year = datepart(year,datecolumn),
, DayOfYear = datepart(dayofyear,datecolumn)
, MaxValue = max(MaxValue)
from yourtable
inner join (
select
Year = datepart(year,datecolumn),
, MaxValue = max(value)
from yourtable
group by datepart(year,datecolumn)
) sub on
sub.Year = yourtable.datepart(year,datecolumn)
and sub.MaxValue = yourtable.value
group by
datepart(year,datecolumn),
datepart(dayofyear,datecolumn)
You didn't mention which RDBMS or SQL dialect you're using. The following will work with T-SQL (MS SQL Server). It may require some modifications for other dialects since date functions tend to change a lot between them.
SELECT
DATEPART(dy, my_date),
MAX(my_number)
FROM
My_Table
WHERE
my_date >= '2008-01-01' AND
my_date < '2009-01-01'
GROUP BY
DATEPART(dy, my_date)
The DAY function could be any function or combination of functions which gives you the days in the format that you're looking to get.
Also, if there are days with no rows at all then they will not be returned. If you need those days as well with a NULL or the highest value from the previous day then the query would need to be altered a bit.
Something like
SELECT dateadd(dd,0, datediff(dd,0,datetime)) as day, MAX(value)
FROM table GROUP BY dateadd(dd,0, datediff(dd,0,datetime)) WHERE
datetime < '2009-01-01' AND datetime > '2007-12-31'
Assuming datetime is your date column, dateadd(dd,0, datediff(dd,0,datetime)) will extract only the date part, and then you can group by that value to get a maximum daily value. There might be a prettier way to get only the date part though.
You can also use the between construct to avoid the less than and greater than.
Group on the date, use the max delegate to get the highest value for each date, sort on the value, and get the first record.
Example:
select top 1 theDate, max(theValue)
from TheTable
group by theDate
order by max(theValue) desc
(The date field needs to only contain a date for this grouping to work, i.e. the time component has to be zero.)
If you need to limit the query for a specific year, use a starting and ending date in a where claues:
select top 1 theDate, max(theValue)
from TheTable
where theDate between '2008-01-01' and '2008-12-13'
group by theDate
order by max(theValue) desc