I am trying to show the count and percentage in a table.
The query I used is this:
DECLARE #BeginDate AS DATETIME
SET #BeginDate = GETDATE();
SELECT TOP 10
s.Title AS Title, COUNT(*) AS TotalSessions
FROM
History s
WHERE
CONVERT(DATE, s.DateStamp) >= DATEADD(DAY, -7, #BeginDate)
AND CONVERT(DATE, s.DateStamp) <= DATEADD(DAY, -1, #BeginDate)
GROUP BY
Title
ORDER BY
TotalSessions DESC
This returns the top 1o records and now
I want to show the percentage value with respect to total as the third column. Can I do this in same query?
I want to show the remaining count as others (if 100 records are there, first 10 rows shows top 10 records and row #11 shows sum of remaining 90 records with title "Others"). Can I do it in the same query?
You can use window functions. Something like this:
SELECT TOP 10 s.Title as Title, count(*) as TotalSessions,
COUNT(*) * 1.0 / SUM(COUNT(*)) OVER ()
FROM History s
WHERE convert(date,s.DateStamp) >= DATEADD(DAY, -7, #BeginDate)
AND convert(date,s.DateStamp) <= DATEADD(DAY, -1, #BeginDate)
GROUP BY Title
ORDER BY TotalSessions DESC
Related
This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed last year.
I am working with group by in SQL Server. I want to select fields that shouldn't be part of group by.
I want to select DishId but it shouldn't be in group by clause. If I add the DishId into group by it repeats the range as shown following.
SELECT v.range, COUNT(*) AS 'occurrences',COUNT(DishID) * SUM(OrderQty) AS [TotalOrders],po.DishID
FROM ( SELECT PgrId,CASE WHEN DATEDIFF(YEAR, p.PgrDOB, GETDATE()) >= 0 AND DATEDIFF(YEAR, p.PgrDOB, GETDATE()) < 10 THEN '0-9'
WHEN DATEDIFF(YEAR, p.PgrDOB, GETDATE()) >= 10 AND DATEDIFF(YEAR, p.PgrDOB, GETDATE()) < 20 THEN '10-19'
WHEN DATEDIFF(YEAR, p.PgrDOB, GETDATE()) >= 20 AND DATEDIFF(YEAR, p.PgrDOB, GETDATE()) < 30 THEN '20-29'
WHEN DATEDIFF(YEAR, p.PgrDOB, GETDATE()) >= 30 AND DATEDIFF(YEAR, p.PgrDOB, GETDATE()) < 40 THEN '30-39'
ELSE '40+'
END AS 'range'
FROM Passenger p
) v inner join PassengerOrder po on v.PgrId = po.PgrID
GROUP BY v.range,po.DishID
Sounds like you want the highest dish in each age range, ordered by total sales descending. There are many other improvements that could be made here but the simplest way is to just generate a row number per range ordered by total sales descending, and wrap that in a CTE, filtered by the first row number.
;WITH cte AS
(
SELECT v.range,
COUNT(*) AS occurrences,
COUNT(DishID) * SUM(OrderQty) AS TotalOrders,
po.DishID,
rn = ROW_NUMBER() OVER (PARTITION BY v.range
ORDER BY COUNT(DishID) * SUM(OrderQty) DESC)
FROM
( SELECT PgrId,
CASE WHEN p.PgrDOB < DATEADD(YEAR, -40, GETDATE()) THEN '40+'
WHEN p.PgrDOB < DATEADD(YEAR, -30, GETDATE()) THEN '30-39'
WHEN p.PgrDOB < DATEADD(YEAR, -20, GETDATE()) THEN '20-29'
WHEN p.PgrDOB < DATEADD(YEAR, -10, GETDATE()) THEN '10-19'
ELSE '0-9'
END AS range
FROM dbo.Passenger p
) v inner join dbo.PassengerOrder po on v.PgrId = po.PgrID
GROUP BY v.range,po.DishID
)
SELECT range, occurrences, TotalOrders, DishID
FROM cte
WHERE rn = 1
ORDER BY TotalOrders DESC;
Output (shown in this db<>fiddle):
range
occurrences
TotalOrders
DishID
40+
2
220
dsh0000001
30-39
2
84
dsh0000001
10-19
1
11
dsh0000001
20-29
1
1
dsh0000001
0-9
1
1
dsh0000001
I fixed a couple of other things, too:
Always use schema name for objects.
Don't use 'single quotes' to delimit column aliases; this makes them too easy to confuse with string literals. Use [square brackets] instead, but don't delimit at all unless you need to. (I talk a little about that here.)
Your DATEDIFF calculation was not accurate to a person's birthday, nor is mine, but if you flip the order you can make a much less complex CASE expression, and when you move functions away from the column, you make it more likely that the query could benefit from a current (or future) index. Lots more at Dating Responsibly.
I need to get some information of a SQL Database, I have and a group of ID which I need to count the number of rows and then display the ID and the Number of rows but only if the number of rows is greater than 3.
I already have the following code but I am unable to put the count(*) in the where clause.
SELECT StaffID, COUNT(*)
FROM StaffAbsence where StartDate > DATEADD(month, -6, getdate())
GROUP BY StaffID
Any suggestions
You need to use the HAVING clause with your GROUP BY statement, e.g.
SELECT StaffID, COUNT(*)
FROM StaffAbsence WHERE StartDate > DATEADD(MONTH, -6, GETDATE())
GROUP BY StaffID HAVING COUNT(*) > 3
Is there a way to run a query for a specified amount of time, say the last 5 months, and to be able to return how many records were created each month? Here's what my table looks like:
SELECT rID, dateOn FROM claims
SELECT COUNT(rID) AS ClaimsPerMonth,
MONTH(dateOn) AS inMonth,
YEAR(dateOn) AS inYear FROM claims
WHERE dateOn >= DATEADD(month, -5, GETDATE())
GROUP BY MONTH(dateOn), YEAR(dateOn)
ORDER BY inYear, inMonth
In this query the WHERE dateOn >= DATEADD(month, -5, GETDATE()) ensures that it's for the past 5 months, the GROUP BY MONTH(dateOn) then allows it to count per month.
And to appease the community, here is a SQL Fiddle to prove it.
Unlike the other two answers, this will return all 5 months, even when the count is 0. It will also use an index on the onDate column, if a suitable one exists (the other two answers so far are non-sargeable).
DECLARE #nMonths INT = 5;
;WITH m(m) AS
(
SELECT TOP (#nMonths) DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-number, 0)
FROM master.dbo.spt_values WHERE [type] = N'P' ORDER BY number
)
SELECT m.m, num_claims = COUNT(c.rID)
FROM m LEFT OUTER JOIN dbo.claims AS c
ON c.onDate >= m.m AND c.onDate < DATEADD(MONTH, 1, m.m)
GROUP BY m.m
ORDER BY m.m;
You also don't have to use a variable in the TOP clause, but this might make the code more reusable (e.g. you could pass the number of months as a parameter).
SELECT
count(rID) as Cnt,
DatePart(Month, dateOn) as MonthNumber,
Max(DateName(Month, dateOn)) as MonthName
FROM claims
WHERE dateOn >= DateAdd(Month, -5, getdate())
GROUP BY DatePart(Month, dateOn)
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');
SELECT SearchTerm, CustomerID, CreatedOn
FROM SearchLog
WHERE CreatedOn >= DATEADD(DAY, DATEDIFF(Day, 0, GETDATE()), -5)
GROUP BY SearchTerm, CustomerID, CreatedOn
I want to add one more column, which will be COUNT(SearchTerm) and I want to order the query by the searchterm which is mostly searched for. and the column should say how many times the searchterm is searched.
Thanks for your help
Try this your group by is wrong if I understand correctly-
SELECT d1.CustomerId,SearchTerm,CreatedOn,d1.TimesSearched
FROM
(
SELECT CustomerID, COUNT(SearchTerm) as TimesSearched
FROM SearchLog
WHERE CreatedOn >= DATEADD(DAY, DATEDIFF(Day, 0, GETDATE()), -5)
GROUP BY CustomerID
ORDER BY COUNT(SearchTerm) desc
) as d1 inner join SearchLog on
d1.CustomerID=SearchLog .CustomerId
Is CreatedOn with or without timestamp?
If it's only the date part you could do:
SELECT s.SearchTerm, s.CustomerID, s.CreatedOn, COUNT(1) AS search_count
FROM SearchLog s
WHERE CreatedOn >= DATEADD(DAY, DATEDIFF(Day, 0, GETDATE()), -5)
GROUP BY s.SearchTerm, s.CustomerID, s.CreatedOn
ORDER BY COUNT(1)
otherwise you need to strip the timestamp somehow (I don't know your SQL dialect)