How to count number of records per day? - sql

I have a table in a with the following structure:
CustID --- DateAdded ---
396 2012-02-09
396 2012-02-09
396 2012-02-08
396 2012-02-07
396 2012-02-07
396 2012-02-07
396 2012-02-06
396 2012-02-06
I would like to know how I can count the number of records per day, for the last 7 days in SQL and then return this as an integer.
At present I have the following SQL query written:
SELECT *
FROM Responses
WHERE DateAdded >= dateadd(day, datediff(day, 0, GetDate()) - 7, 0)
RETURN
However this only returns all entries for the past 7 days. How can I count the records per day for the last 7 days?

select DateAdded, count(CustID)
from Responses
WHERE DateAdded >=dateadd(day,datediff(day,0,GetDate())- 7,0)
GROUP BY DateAdded

select DateAdded, count(CustID)
from tbl
group by DateAdded
about 7-days interval it's DB-depending question

SELECT DateAdded, COUNT(1) AS NUMBERADDBYDAY
FROM Responses
WHERE DateAdded >= dateadd(day,datediff(day,0,GetDate())- 7,0)
GROUP BY DateAdded

This one is like the answer above which uses the MySql DATE_FORMAT() function. I also selected just one specific week in Jan.
SELECT
DatePart(day, DateAdded) AS date,
COUNT(entryhash) AS count
FROM Responses
where DateAdded > '2020-01-25' and DateAdded < '2020-02-01'
GROUP BY
DatePart(day, DateAdded )

If your timestamp includes time, not only date, use:
SELECT DATE_FORMAT('timestamp', '%Y-%m-%d') AS date, COUNT(id) AS count FROM table GROUP BY DATE_FORMAT('timestamp', '%Y-%m-%d')

You could also try this:
SELECT DISTINCT (DATE(dateadded)) AS unique_date, COUNT(*) AS amount
FROM table
GROUP BY unique_date
ORDER BY unique_date ASC

SELECT count(*), dateadded FROM Responses
WHERE DateAdded >=dateadd(day,datediff(day,0,GetDate())- 7,0)
group by dateadded
RETURN
This will give you a count of records for each dateadded value. Don't make the mistake of adding more columns to the select, expecting to get just one count per day. The group by clause will give you a row for every unique instance of the columns listed.

select DateAdded, count(DateAdded) as num_records
from your_table
WHERE DateAdded >=dateadd(day,datediff(day,0,GetDate())- 7,0)
group by DateAdded
order by DateAdded

Unfortunately the best answer here IMO is a comment by #Profex on an incorrect answer , but the solution I went with is
SELECT FORMAT(DateAdded, 'yyyy-MM-dd'), count(CustID)
FROM Responses
WHERE DateAdded >= dateadd(day,datediff(day,0,GetDate())- 7,0)
GROUP BY FORMAT(DateAdded, 'yyyy-MM-dd')
ORDER BY FORMAT(DateAdded, 'yyyy-MM-dd')
Note that I haven't tested this SQL since I don't have the OP's DB , but this approach works well in my scenario where the date is stored to the second
The important part here is using the FORMAT(DateAdded, 'yyyy-MM-dd') method to drop the time without losing the year and month , as would happen if you used DATEPART(day, DateAdded)

When a day among last 7 days, has no record means, the following code will list out that day with count as zero.
DECLARE #startDate DATE = GETDATE() - 6,
#endDate DATE = GETDATE();
DECLARE #daysTable TABLE
(
OrderDate date
)
DECLARE #daysOrderTable TABLE
(
OrderDate date,
OrderCount int
)
Insert into #daysTable
SELECT TOP (DATEDIFF(DAY, #startDate, #endDate) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, #startDate)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b;
Insert into #daysOrderTable
select OrderDate, ISNULL((SELECT COUNT(*) AS OdrCount
FROM [dbo].[MyOrderTable] odr
WHERE CAST(odr.[CreatedDate] as date) = dt.OrderDate
group by CAST(odr.[CreatedDate] as date)
), 0) AS OrderCount from #daysTable dt
select * from #daysOrderTable
RESULT
OrderDate     OrderCount
2022-11-22     42
2022-11-23     6
2022-11-24     34
2022-11-25     0
2022-11-26     28
2022-11-27     0
2022-11-28     22

SELECT DATE_FORMAT(DateAdded, '%Y-%m-%d'),
COUNT(CustID)
FROM Responses
GROUP BY DATE_FORMAT(DateAdded, '%Y-%m-%d');

Related

SQL query result needs to be summed

Code is
select customerid, count(campaignid) as T, Convert (varchar, CreatedOn,23) from customerbenefits
where campaignid='6EDBB808-1A91-4B1D-BE1D-27EF15C5D4C7'
and createdon between '2019-09-01' and '2019-10-01'
group by customerid,CreatedOn
having count(campaignid)>1
order by createdon desc
Result is
-- id / count /time
--18655680-3B5E-4001-1984-00000000 / 12 /2019-09-30
--18655680-3B5E-4001-1984-00000000 / 7 / 2019-09-30
--18655680-3B5E-4001-1984-00000000 / 6 / 2019-09-30
I want result as
-- id / count / time
-- 18655680-3B5E-4001-1984-00000000 / 25/ 2019-09-30
I want it grouped to time filter and sum counts.
How can I change my query?
Use two levels of aggregation:
select customerid, dte, sum(T)
from (select customerid, count(*) as T, convert(varchar(255), CreatedOn, 23) as dte
from customerbenefits
where campaignid = '6EDBB808-1A91-4B1D-BE1D-27EF15C5D4C7' and
createdon >= '2019-09-01' and
createdon < '2019-10-01'
group by customerid, CreatedOn
having count(*) > 1
) t
group by customerid, dte
order by createdon desc ;
Notice that I changed the date comparisons so midnight on 2019-10-01 is not included in the data for September.

get last 3 month on year in sql server

I want to get last 3 months name from current month. For example current month is December. So, I want get like this October, November and December.
This is my query:
SELECT CONVERT(CHAR, DATENAME(MONTH, IssueDate)) AS MonthName, ItemId
FROM dbo.Issue AS Issue
GROUP BY CONVERT(CHAR, DATENAME(MONTH, IssueDate)), ItemId
HAVING (ItemId = 427)
This returns:
But, my need is:
N.B. When December month close and January month open then October auto excluded as like (November, December and January)
this link is my Database only 2 table (size-243 KB with Zip) on the google drive https://goo.gl/S4m0R5
Add a date diff in a where clause to filter to the last 3 months, and then order by the month number at the end:
SELECT CONVERT(CHAR, DATENAME(MONTH, [IssueDate])) AS MonthName, ItemId
FROM [dbo].[Issue] AS Issue
WHERE datediff(m, [IssueDate], getdate()) between 0 and 2
GROUP BY CONVERT(CHAR, DATENAME(MONTH, [IssueDate])), ItemId, MONTH(IssueDate)
HAVING (ItemId= 427)
order by MONTH(IssueDate);
You can use DATEADD function:
WHERE IssueDate >= dateadd( month, -2, dateadd( day, -datepart( day, getdate() ) + 1, cast( getdate() as date ) ) )
That will give you IssueDate >= '2015-10-01' given today.
That will also work with index you have on IssueDate, if you start doing something like DATEADD / DATEDIFF etc. on IssueDate then the index can only be scanned end-to-end because it needs to processs all rows in the table so renders the index significantly less effective.
DECLARE #t TABLE
(
IssueDate DATETIME,
ItemId INT
)
INSERT INTO #t (IssueDate, ItemId)
VALUES
('20160105', 427),
('20151212', 427),
('20151213', 427),
('20151110', 427),
('20151001', 427),
('20150905', 427)
SELECT DATENAME(MONTH, dt)
FROM (
SELECT DISTINCT TOP(3) DATEADD(MONTH, DATEDIFF(MONTH, 0, IssueDate), 0) AS dt
FROM #t
WHERE ItemId = 427
ORDER BY dt DESC
) t
results -
------------------------------
January
December
November
You can use a recursive CTE to get month names for the last 12 months and then limit it to the last 3 month names in the second part of the query:
;WITH months(MonthNumber) AS
(
SELECT 0
UNION ALL
SELECT MonthNumber+1
FROM months
WHERE MonthNumber < 12
)
SELECT DATENAME(MONTH,DATEADD(MONTH,-MonthNumber,GETDATE())) AS [month]
FROM dbo.Issue AS Issue
CROSS JOIN months m
WHERE m.MonthNumber <3
GROUP BY DATENAME(MONTH,DATEADD(MONTH,-MonthNumber,GETDATE())) , ItemId
HAVING (ItemId = 427)

SQL: How can I select the first and last date for each customer?

I can't seem to figure this one out. I have a table of transactions (lots of them), with date, customer ID etc.
I want to select, for a specific day, the datetime for only the first AND the last transaction for each customer on that day, like so:
custID FirstT LastT
318 08:05 18:35
968 03:21 13:54
488 12:34 14:28
SQL Server 2008. Sounds simple enough but I'm about ready to throw in the towel... Would appreciate help..
SELECT
custID,
MIN(transaction_date) AS FirstT,
MAX(transaction_date) AS LastT
FROM
yourTable
WHERE
transaction_date >= '2014-04-01'
AND transaction_date < '2014-04-02'
GROUP BY
custID
Try this:
SELECT custid, DATEADD(dd, 0, DATEDIFF(dd, 0, date)) Date, MIN(date) FirstT, MAX(date) LastT
FROM transactions
GROUP BY custid, DATEADD(dd, 0, DATEDIFF(dd, 0, date))
Don't know your schema but you should be doing something like this:
select custID, max(transactionDate), min(transactionDate)
where cast(transactionDate as date) = '20140101'
group by custID
SELECT * FROM
(SELECT custID, transaction_date FROM transactions ORDER BY transaction_date LIMIT 1) t
UNION
SELECT * FROM
(SELECT custID, transaction_date FROM transactions ORDER BY transaction_date DESC LIMIT 1) t1

How to select another piece of data in a record returned by a max() command

thanks for taking the time to help me out! I'm trying to make SQL do something that I imagine is easy for anybody who knows SQL, but I'm beating my head against at this point.
I have me a little table like this -
Update Order UpdateDate OrderDate
9297 3590 2012-12-06 2012-12-06
9298 3590 2012-12-06 2012-12-06
9356 3590 2012-12-07 2012-12-06
9369 3590 2012-12-08 2012-12-06
9381 3590 2012-12-10 2012-12-06
My goal is to find orders that have not been updated in the last 3 days.
The ugly version of what I'm trying to do is something like this -
Select order from orderstable
where cast(max(updatedate)-getdate() as int) >3
The goal here is to have the command return "orders" that have not been updated in the last 3 days. My current problem is I don't know how to make SQL focus on just the "most recent" updatedate for the order.
The easiest way is just a date comparison:
select *
from orderstable ot
where datediff(day, updatedate, getdate()) > 3
I see, you have multiple records for each order and you want orders that have no update in the past three days. I would do this with an aggregation:
select order
from orderstable ot
group by order
having min(datediff(day, updatedate, getdate())) > 3
You can also do it by looking for orders that don't have updates in the last three days:
select distinct order
from orderstable
where order not in (select order
from orderstable
where datediff(day, updatedate, getdate()) <= 3)
First off, I'd avoid using DATEDIFF as it is not sargable: http://weblogs.sqlteam.com/dang/archive/2009/03/07/Low-Hanging-Fruit-of-Sargable-Expressions.aspx
;WITH MaxOrders AS (
SELECT Order, MAX(UpdateDate) MaxUpdateDate
FROM orderstable
GROUP BY Order
)
SELECT Order
FROM MaxOrders
WHERE MaxUpdateDate < DATEADD(day,-3,GETDATE());
In this example, DATEADD is sargable because there is a static value ,GETDATE(), in the function. If the function had column values in it, it would not be sargable. In other words, if you were to change it to this:
WHERE DATEADD(day,3,MaxUpdateDate) < GETDATE();
it would no longer be sargable, as all column values would have to be evaluated in the function before a criteria match is determined. This is the problem with using DATEDIFF in the where clause. It has column values in the function. This is going to be very expensive on big data sets.
Why not use getdate() to get the current date?
So something like this:
SELECT order FROM orderstable
WHERE datediff(day, updatedate, getdate()) > 3
(Yes, this does not answer the question asked in the title - but it does answer the problem posed in the body of the question)
To answer the question asked in the title, how about:
SELECT order FROM orderstable
WHERE datediff(day, orderdate, (select max(updatedate) from orderstable)) > 3
DECLARE #T TABLE(
[Update] INT,
[Order] INT,
UpdateDate DATE,
OrderDate DATE
)
INSERT INTO #T VALUES
(9297,3590,'2012-12-06','2012-12-06'),
(9298,3590,'2012-12-06','2012-12-06'),
(9356,3590,'2012-12-07','2012-12-06'),
(9369,3590,'2012-12-08','2012-12-06'),
(9381,3590,'2012-12-10','2012-12-06'),
(9382,3591,'2012-12-07','2012-12-06'),
(9383,3591,'2012-12-08','2012-12-06'),
(9384,3592,'2012-12-07','2012-12-06'),
(9385,3592,'2012-12-09','2012-12-06'),
(9386,3593,'2012-12-05','2012-12-06'),
(9387,3593,'2012-12-07','2012-12-06')
--Assuming we don't care about time, cast to DATE to remove time values from GETDATE() function.
--It also assumes that today is inclusive.
;WITH RECENT_UPDATES_CTE
AS (
SELECT [Order],MAX([UpdateDate]) [LastUpdateDate] FROM #T
GROUP BY [Order]
)
SELECT DISTINCT T.[Order] FROM #T T
LEFT JOIN RECENT_UPDATES_CTE C ON C.[Order] = T.[Order]
WHERE C.LastUpdateDate <= DATEADD(DAY,-3,CAST(GETDATE() AS DATE))
Use OVER clause for finding MAX(UpdateDate)
;WITH cte AS
(
SELECT *,
DATEDIFF(d, MAX(UpdateDate) OVER (PARTITION BY [Order]), GETDATE()) AS diff_date
FROM orderstable
)
SELECT [Update], [Order], UpdateDate, OrderDate
FROM cte
WHERE diff_date > 3
Demo on SQLFiddle

SQL Query for hours of the day

I have a SQL Server 2008 database with a table that has a column (datetime datatype) recording when an order is placed.
I would like to run a query that will give a breakdown of total amount of orders per hour on any given date or date range but am unsure of the best way to write the query.
It should be something along the lines of:
SELECT DATEPART(HOUR, OrderDate) AS [Hour], COUNT(*) AS [Count]
FROM [Orders]
WHERE OrderDate BETWEEN #StartDate AND #EndDate --or whatever criteria
GROUP BY DATEPART(HOUR, OrderDate)
You can use DATEPART and GROUP BY to get this:
SELECT DATEPART(Hour, DateField), COUNT(*)
FROM Orders
WHERE Date = #DateParam -- or your range check here
GROUP BY DATEPART(Hour, Datefield)
I believe it would be as simple as this:
SELECT
[Hour] = DATEPART(HOUR,DateTimeField)
,Orders = COUNT(*)
FROM
tblORDERS
GROUP BY
DATEPART(HOUR,DateTimeField)
You're probably looking for something like:
;WITH OrdersPerHour AS
(
SELECT
CAST(OrderDate AS DATE) 'OrderDate',
DATEPART(HOUR, OrderDate) AS 'Hour',
SalesAmount
FROM
dbo.YourOrderTable
)
SELECT
OrderDate, Hour,
COUNT(*), -- number of orders
SUM(SalesAmount) -- sum of the amounts for those orders
FROM
OrdersPerHour
WHERE
OrderDate = '20120113' -- or whatever you're looking for
GROUP BY
OrderDate, Hour
Not sure if you mean the total sum of the order amounts - or the number of orders - when you say breakdown of total amount of orders per hour - if you need the count, just use COUNT(*) instead of the SUM(SalesAmount) I put in my query.