SQL Count Total ROWS for an ID - sql

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

Related

Calculate percentage along with count

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

SQL to count records per hour and count how many hours that total record count was greater than a value

Using SQL Server 2014. I have a list of records that are time stamped and I would like to count how many records there are per hour then count how many hours each day that the record count exceeded a given number, say 20.
Here's what I have so far:
select count(distinct datepart(hour, convert(datetime, OrderStateDate))) Count_HoursOver,
datepart(YEAR, convert(datetime, OrderStateDate)) Date_YEAR,
datepart(month, convert(datetime, OrderStateDate)) Date_MONTH,
datepart(day, convert(datetime, OrderStateDate)) Date_DAY
from Reporting.dbo.Orders
group by datepart(YEAR, convert(datetime, OrderStateDate)),
datepart(month, convert(datetime, OrderStateDate)),
datepart(day, convert(datetime, OrderStateDate))
having count(idscript) >= 20
The results aren't correct and I can't make sense of what's being returned and why. Am I using HAVING incorrectly? Any advice would be appreciated!
You kind of have a 2-part question here
I would like to count how many records there are per hour
You can create a query that returns tuples (RecordsPerHour,HOUR,YEAR,MONTH,DAY) as follows:
SELECT
count(*) as RecordsPerHour,
datepart(hour,convert(datetime,OrderStateDate)) as Date_HOUR,
datepart(year,convert(datetime,OrderStateDate)) as Date_YEAR,
datepart(month,convert(datetime,OrderStateDate)) as Date_MONTH,
datepart(day,convert(datetime,OrderStateDate)) as Date_DAY
FROM Reporting.dbo.Orders
GROUP BY
datepart(year,convert(datetime,OrderStateDate)),
datepart(month,convert(datetime,OrderStateDate)),
datepart(day,convert(datetime,OrderStateDate)),
datepart(hour,convert(datetime,OrderStateDate))
then count how many hours each day that the record count exceeded a given number, say 20
To do this, use the query from the first part of your question in a nested query, using a HAVING clause to filter only hours that contain at least 20 orders.
On the outer query, group by (YEAR,MONTH,DAY) to determine the number of hours in that day with at least 20 orders:
SELECT
count(*) as HoursWithAtLeast20Orders,
Date_YEAR,
Date_MONTH,
Date_DAY
FROM
(SELECT
datepart(hour,convert(datetime,OrderStateDate)) as Date_HOUR,
datepart(year,convert(datetime,OrderStateDate)) as Date_YEAR,
datepart(month,convert(datetime,OrderStateDate)) as Date_MONTH,
datepart(day,convert(datetime,OrderStateDate)) as Date_DAY
FROM Reporting.dbo.Orders
GROUP BY
datepart(year,convert(datetime,OrderStateDate)),
datepart(month,convert(datetime,OrderStateDate)),
datepart(day,convert(datetime,OrderStateDate)),
datepart(hour,convert(datetime,OrderStateDate))
HAVING count(*) >=20) as t
GROUP BY
Date_YEAR,
Date_MONTH,
Date_DAY
First round to hour then round to day
SELECT
count(*) as [hours with 20+ Orders],
dateadd(day, datediff(day,'20000101',dt_hour_rounded),'20000101') as dt_day_rounded
FROM (
SELECT
count(*) as OrdersInHour,
dateadd(hour, datediff(hour,'20000101',OrderStateDate),'20000101') as dt_hour_rounded
FROM Reporting.dbo.Orders
GROUP BY dateadd(hour, datediff(hour,'20000101',OrderStateDate),'20000101')
) t
GROUP BY dateadd(day,datediff(day,'20000101',dt_hour_rounded),'20000101')
WHERE OrdersInHour >= 20

Building a scoreboard - need to combine the values of two different referrals into one total sum

I'm building a simple scoreboard. It's basically a summed up list of every employee in the company who brings in external users ("referrals"). The list is simply done by grouping on the last 3 letters of the referral (= the employees initials). However, one of the employees use two different referrals and I need to select and sum these two referrals into one total sum (so I can use that value to order by on my scoreboard).
A normal referral looks like this: "%_abc". The employee in question has two referrals: "%_xyz" and "RE%".
This is the current code:
SELECT
RIGHT(Referral, 3) [Referral], COUNT(*) [Total]
FROM TableName
WHERE
CAST(Created AS DATE) = CAST(DATEADD(DAY, -1, GETDATE()) AS DATE)
AND
(
Referral LIKE '%_abc'
OR
Referral LIKE '%_xyz'
...
)
GROUP BY RIGHT(Referral, 3)
ORDER BY [Total] DESC
I solved my problem with the following code. Any optimisation tips are welcome.
SELECT Referral, SUM(Total) AS Total FROM
(
SELECT RIGHT(Referral, 3) [Referral], COUNT(*) [Total]
FROM TableName
WHERE
CAST(Created AS DATE) = CAST(GETDATE() AS DATE)
AND
(
Referral LIKE '%_abc'
OR
Referral LIKE '%_xyz'
...
)
GROUP BY RIGHT(Referral, 3)
UNION ALL
SELECT 'xyz' AS Referral, COUNT(*) [Total]
FROM TableName
WHERE
CAST(Created AS DATE) = CAST(GETDATE() AS DATE)
AND
LEFT(Referral, 2) = 'RE'
) t
GROUP BY t.Referral
ORDER BY Total DESC

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

How to count number of records per month over a time period

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)