How to query to get totals for last seven days? - sql

I am using SQL Server 2008.
I want to write a query that gives me total activity for a number of given days. Specifically, I want to count total votes per day for the last seven days.
My table looks like this:
VoteID --- VoteDate -------------- Vote --- BikeID
1 2012-01-01 08:24:25 1 1234
2 2012-01-01 08:24:25 0 5678
3 2012-01-02 08:24:25 1 1289
4 2012-01-03 08:24:25 0 1234
5 2012-01-04 08:24:25 1 5645
6 2012-01-05 08:24:25 0 1213
7 2012-01-06 08:24:25 1 1234
8 2012-01-07 08:24:25 0 1125
I need my results to look like this
VoteDate ---- Total
2012-01-01 5
2012-01-02 6
2012-01-03 7
2012-01-04 1
2012-01-05 3
My thought is that I have to do something like this:
SELECT SUM(CASE WHEN Vote = 1 THEN 1 ELSE 0 END) AS Total
FROM Votes
GROUP BY VoteDate
This query doesn't work because it counts only votes that occurred (almost exactly) at the same time. Of course, I want to look only at a specific day. How do I make this happen?

Cast it as a date:
SELECT
cast(VoteDate as date) as VoteDate,
SUM(CASE WHEN Vote = 1 THEN 1 ELSE 0 END) AS Total
FROM Votes
WHERE VoteDate between dateadd(day, -7, GETDATE()) and GETDATE()
GROUP BY cast(VoteDate as date)
Your VoteDate column is a datetime, but you just want the date part of it. The easiest way to do that is to cast it as a date type. You can read more about SQL Server date types here.
And if your Vote column is either 1 or 0, you can just do sum(vote) as Total instead of doing the case statement.

SELECT SUM(Vote) As Total, YEAR(VoteDate),Month(VoteDate),Day(VoteDate)
FROM Votes
Group By YEAR(VoteDate),Month(VoteDate),Day(VoteDate)
Some SQL Server functions that may be of interest
Some MySQL functions that may be of interest

Related

SELECTING records based on unique date and counting how many records on that date

I have a table that I'm going to simplify. Here's what it looks like:
tid session pos dateOn
-----------------------------------------------
1 23 0 12/24/2020 1:00:00
2 23 1 12/24/2020 1:01:23
3 12 0 12/24/2020 1:02:43
4 23 2 12/24/2020 1:04:01
5 23 3 12/24/2020 1:04:12
6 45 0 12/26/2020 4:23:15
This table tells me that there were 2 unique sessions 12/24/2020 and 1 on 12/26.
How do I write my SQL statement so that I get a result like this:
date recordCount
----------------------------
12/24/2020 2
12/26/2020 1
You should simply be able to convert to a date and aggregate:
select convert(date, dateon), count(distinct session)
from t
group by convert(date, dateon)
order by convert(date, dateon);

SQL how to count but only count one instance if two columns match?

Wondering how to select from a table:
FIELDID personID purchaseID dateofPurchase
--------------------------------------------------
2 13 147 2014-03-21 00:00:00
3 15 165 2015-03-23 00:00:00
4 13 456 2018-03-24 00:00:00
5 1 133 2018-03-21 00:00:00
6 23 123 2013-03-22 00:00:00
7 25 456 2013-03-21 00:00:00
8 25 456 2013-03-23 00:00:00
9 22 456 2013-03-28 00:00:00
10 25 589 2013-03-21 00:00:00
11 82 147 1991-10-22 00:00:00
12 82 453 2003-03-22 00:00:00
I'd like to get a result table of two columns: weekday and the number of purchases of each weekday, but only count the distinct days of purchases if done by the same person on the same day - for example since personID 25 purchased two things on 2013-03-21, that should only count as one 'thursday' instead of 2.
Basically, if the personID and the dateofPurchase are the same for more than one row, only count it once is what I want.
Here is what I have currently: It does everything correctly except it will count the above scenario under the thursday twice, when I would only want to add one:
SELECT v.wkday as day, COUNT(*) as 'absences'
FROM dbo.AttendanceRecord pr CROSS APPLY
(VALUES (CASE WHEN DATEPART(WEEKDAY, date) IN (1, 7)
THEN 'Weekend'
ELSE DATENAME(WEEKDAY, date)
END)
) v(wkday)
GROUP BY v.wkday;
to clarify:
If an item is purchased for at least one puchaseID on a specific day they will be counted as purchased for that day, and do not need to be counted again for each new purchase ID on that day.
I think you want to count distinct persons, so that would be:
COUNT(DISTINCT personid) as absences
Note that single quotes are not appropriate around column aliases. If you need to escape them, use square braces.
EDIT:
If you want to count distinct person-days, then you can use:
COUNT(DISTINCT CONCAT(personid, ':', dateofpurchase) as absences

Getting date difference between consecutive rows in the same group

I have a database with the following data:
Group ID Time
1 1 16:00:00
1 2 16:02:00
1 3 16:03:00
2 4 16:09:00
2 5 16:10:00
2 6 16:14:00
I am trying to find the difference in times between the consecutive rows within each group. Using LAG() and DATEDIFF() (ie. https://stackoverflow.com/a/43055820), right now I have the following result set:
Group ID Difference
1 1 NULL
1 2 00:02:00
1 3 00:01:00
2 4 00:06:00
2 5 00:01:00
2 6 00:04:00
However I need the difference to reset when a new group is reached, as in below. Can anyone advise?
Group ID Difference
1 1 NULL
1 2 00:02:00
1 3 00:01:00
2 4 NULL
2 5 00:01:00
2 6 00:04:00
The code would look something like:
select t.*,
datediff(second, lag(time) over (partition by group order by id), time)
from t;
This returns the difference as a number of seconds, but you seem to know how to convert that to a time representation. You also seem to know that group is not acceptable as a column name, because it is a SQL keyword.
Based on the question, you have put group in the order by clause of the lag(), not the partition by.

Getting a count by date based on the number of observations with encompassing date ranges

I am working with a table in Microsoft Access whereby I have 2 columns with a start and end date.
I want to get the count by date of the number of rows with date ranges that encompass the date in the output table.
Input Data
Start Date End Date
01/02/2017 03/02/2017
07/02/2017 19/02/2017
09/02/2017 19/02/2017
11/02/2017 12/02/2017
12/02/2017 17/02/2017
Desired Output
Date Count
01/02/2017 1
02/02/2017 1
03/02/2017 1
04/02/2017 0
05/02/2017 0
06/02/2017 0
07/02/2017 1
08/02/2017 1
09/02/2017 2
10/02/2017 2
11/02/2017 3
12/02/2017 4
13/02/2017 3
14/02/2017 3
15/02/2017 3
16/02/2017 3
17/02/2017 3
18/02/2017 2
19/02/2017 2
20/02/2017 0
For this project, I have to use Microsoft Access 2010, so a solution in either SQL code or design view input would be great.
Any help on this would be appreciated. Thanks!
Use the below query to get the required result. You can also change the column with respect to your requirements
SELECT END_DATE AS DATE, COUNT(*) AS COUNT FROM TABLE_NAME
GROUP BY END_DATE ORDER BY END_DATE;

SUM rows by week syntax

I am using the following query
SELECT CONVERT(date,lot.Killdate) as KillDate
,lot.[LotNo]
,lot.[HotWeight]
,lot.[AverageYieldGrade]
,(lot.HeadShorn + lot.HeadUnshorn) as 'Total'
,(lot.HotWeight) / (lot.HeadShorn + lot.HeadUnshorn) as 'AvgWeight'
,date.Date
,date.WeekOfYear
FROM [LambLot].[dbo].[LotHeader] lot, Master_Dim.dbo.DateDim date
WHERE CONVERT(date,lot.KillDate) = date.Date
and lot.KillLocation = 1
AND lot.HeadShorn > 0
AND lot.HeadUnshorn > 0
AND date.Year = 2016
group by lot.LotNo, lot.HeadShorn, lot.HeadUnshorn, lot.HotWeight lot.AverageYieldGrade, lot.KillDate, date.Date, date.WeekOfYear
order by date.WeekOfYear asc
Here is a copy of the output
KillDate LotNo HotWeight AverageYieldGrade Total AvgWeight Date WeekOfYear
1 2016-01-04 102 21603.5 2.28 348 62.0790229885057 2016-01-04 2
2 2016-01-04 103 2305.3 1.42 53 43.4962264150943 2016-01-04 2
3 2016-01-04 105 1159 0 17 68.1764705882353 2016-01-04 2
4 2016-01-04 108 1493.6 0 39 38.2974358974359 2016-01-04 2
5 2016-01-04 109 2982.8 0 80 37.285 2016-01-04 2
What i would like to do is sum each row into the weekofyear. Essentially giving me 52 rows of output, with sums of each value in each column shown. Is there a way to do this?
If you need to SUM by just WeekOfYear, you need to GROUP BY just week of year. You have to decide how you handle the other values, here's one way that may make sense (with some expected output it'd be easier to figure out what you're really looking for):
SELECT CONVERT(date, MAX(lot.Killdate)) as KillDate
,MAX(lot.[LotNo]) -- ?? Does this really belong in this query?
,SUM(lot.[HotWeight])
,AVG(lot.[AverageYieldGrade])
,(SUM(lot.HeadShorn) + SUM(lot.HeadUnshorn)) as 'Total'
,SUM(lot.HotWeight) / (SUM(lot.HeadShorn) + SUM(lot.HeadUnshorn)) as 'AvgWeight'
,MAX(date.Date)
,date.WeekOfYear
FROM [LambLot].[dbo].[LotHeader] lot, Master_Dim.dbo.DateDim date
WHERE CONVERT(date,lot.KillDate) = date.Date
and lot.KillLocation = 1
AND lot.HeadShorn > 0
AND lot.HeadUnshorn > 0
AND date.Year = 2016
group by date.WeekOfYear
order by date.WeekOfYear asc
Just remember: whatever columns you GROUP BY will be factored into how a distinct group is figured out. Anything you don't have in your GROUP BY but want in your output just needs some kind of aggregate function (such as MIN, MAX, AVG, SUM, COUNT, etc.).