Trying to a Select Count where it needs to count the difference between a certain date and current date - sql

It's not quite working for me!
My query is as follows:
SELECT COUNT (*) as [generic]
FROM [Log]
Where value IN (Select ID, tsSendDocument, sysReceivedFrom
WHERE sysReceivedFrom = 'generic' AND
DATEDIFF(hour, tsSendDocument, GetDate()) > 2)
So, what am I doing wrong here?
I want it to to count every time the tsSendDocument column is older than 2 hours. It will eventually give me a count that's equal to 1. I have a table set up to alert me if the value = 1, which means that the tsSendDocument is older than 2 hours.
Do this make any sense?

As per your comment, I've understood that you want to check if the last entry is older than 2 hours, so this should work:
SELECT TOP 1 CASE WHEN tsSendDocument < DATEADD(HOUR, -2, GETDATE()) THEN 1 ELSE 0 END AS [generic]
FROM [Log]
ORDER BY tsSendDocument DESC

I think you want only aggregation :
Select COUNT(*)
FROM Log
WHERE sysReceivedFrom = 'generic' AND
DATEDIFF(hour, tsSendDocument, GetDate()) > = 2;
subquery will only return one expression when you specified IN orNOT IN clause.

Related

How to i find records in the last month that do not have a "Date created" column

Im trying to find records that have not had notes created during the last 1 month. The table only registers when a note is created.
I am trying to find NULL values, but that would not be the correct logic
SELECT *
FROM vpersonnotesalldata AS pn
WHERE pn.flddatecreated > '20190501'
AND pn.fldnotedatecreated < '20190530'
If you want records which don't have a note in last 30 days, try this:
select p.* from person p where personid not in (
select personid from Note where dateCreated < dateadd(d, -30, GetDate())
)
Obviously use your actual table names in your sql
Try this with example last month
SELECT *
FROM vpersonnotesalldata AS pn
WHERE pn.NoteColumnHERE IS NULL
AND pn.CreateDateColumnHERE
BETWEEN '01.05.2019'
AND '31.05.2019'
It picks all pn.NoteColumnHERE which are NULL in the Span of pn.CreateDateColumnHERE BETWEEN 01.05. and 31.05.
I hope the Date Input is correct for your SQL Version. In Microsoft SQL it is working!
The performance will be much better if you use EXISTS / NOT EXISTS instead of IN / NOT IN
SELECT *
FROM Client C
WHERE NOT EXISTS (
SELECT 1
FROM vpersonnotesalldata
WHERE
fldClientNumber = C.fldClientNumber
AND fldnotedatecreated BETWEEN
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) --First day of previous month
AND DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1) --Last Day of previous month
)

Get count of rows where date is less than today

I have done the following to get a list of count for today having a date less than today. I have done the following code:
select SUM(CASE WHEN (EXPIRYDAYE>= CONVERT(date, GETDATE())) > 1
then 1
else 0
end)
from bottles;
However, I am getting this as error:
Incorrect syntax near '>'.
Note that I need to do the count that way. So please help me on the syntax in this way of doing the count. Thanks
you have to try like below
select SUM(CASE WHEN EXPIRYDAYE< CONVERT(date, GETDATE()) then 1 else 0 end)
In your sql query case when statement is wrong
CASE WHEN (EXPIRYDAYE>= CONVERT(date, GETDATE())) > 1 -- here last >1 is illogical
Try this
SELECT
SUM(
CASE WHEN EXPIRYDAYE< CAST(GETDATE() AS DATE)
THEN 1
ELSE 0 END)
You don't need the > symbol before the 1
Following simple query should work for your case. You don't need CASE WHEN for this.
SELECT COUNT(*) TotalCount
FROM YOUR_TABLE WHERE EXPIRYDAYE < CAST(GETDATE() AS DATE)
Note that I need to do the count that way. So please help me on the
syntax in this way of doing the count.
I am not sure why you want to do it in a specific way whereas more efficient query is available.

Using the result of a SQL subquery in multiple joins

I have a subquery :-
SELECT TOP 1 Months.EndDate
FROM (SELECT TOP 1 *
FROM FinancialMonth
WHERE FinancialMonth.EndDate > DATEADD(MONTH, -12, GETDATE())
AND FinancialMonth.StartDate < GETDATE()
ORDER BY Period ASC) Months
ORDER BY Months.Period DESC
This returns the Month End Date and works for any number of months ago in the last year simply by changing the second TOP 1.
My problem is that I need to use this date in a number of LEFT JOIN statements where I compare it to two tables. I also need to return it in the final SELECT SUM statement.
By manually inputting the date to the LEFT JOIN queries I can run the main query and have a result back in under 1 second. However if I place this subquery against each LEFT JOIN it can take well over a minute to run. Given that I would like to run this query for each of the last 12 months this is going to tie the server up for an unacceptable amount of time.
Is there any way of running a query and then referencing this result within the LEFT JOIN subqueries without it running over and over. At present it appears to running well over 100k times.
Already i dont understand why you use 2 x top 1 (a top 1 in top 1 give 1 row), you query can be simplify to :
SELECT TOP 1 EndDate
FROM FinancialMonth
WHERE FinancialMonth.EndDate > DATEADD(MONTH, -12, GETDATE())
AND FinancialMonth.StartDate < GETDATE()
ORDER BY Period ASC
Now for what you want you can do Something like that:
with TblEndDate as (
SELECT TOP 1 EndDate
FROM FinancialMonth
WHERE FinancialMonth.EndDate > DATEADD(MONTH, -12, GETDATE())
AND FinancialMonth.StartDate < GETDATE()
ORDER BY Period ASC
)
select * from othertable f1
left outer join TblEndDate f2 on f1.DateInOthertable>=f2.EndDate

SQL Query Statement Return Different Results

Newbie to the forum. I am trying to write a MS SQL query that returns the number of unique user logons in the last 24 hours. I am not a SQL expert. Below are two queries that I have. The 2nd one is and extension of the first where I want to group the result by date and hour. My question is, the 2nd query return result larger than the first. What am I missing? Thanks\
1ST
SELECT COUNT(DISTINCT(RESOURCE_ID)) AS 'UniqueLogonUsers'
FROM live.AUDIT_LOG WITH (NOLOCK)
WHERE AUDIT_TYPE = 0 AND AUDIT_TIME >= DateAdd(hh, -24, GETDATE())
2ND
SELECT CAST(AUDIT_TIME AS DATE) AS 'WhichDate',
DATEPART(hh, AUDIT_TIME) AS 'WhichHour',
COUNT(DISTINCT(RESOURCE_ID)) AS 'UniqueLogonUsers'
FROM live.AUDIT_LOG WITH (NOLOCK)
WHERE AUDIT_TYPE = 0 AND AUDIT_TIME >= DateAdd(hh, -24, GETDATE())
GROUP BY CAST(AUDIT_TIME AS DATE), DATEPART(hh, AUDIT_TIME)
ORDER By CAST(AUDIT_TIME AS DATE) DESC, DATEPART(hh, AUDIT_TIME) DESC
Your first query should only return 1 row - a count of logins in the last 24 hours. Your second breaks that count into rows for each Day/Hour combination, so thus will have more rows - one for each combination, with the counts of the logins during that hour.
Could it be because you are using GETDATE() which would have returned a different value each time? Can you try putting a fixed date in there instead of GETDATE()?

SQL - alert if there is a new unique record inserted in the last hour

I am trying to find an elegant solution in the form of a SQL query for the following problem.
New records will be inserted in the Log table.
I need to detect any new records (inserted in the last hour) that I haven't seen before and generate an alert (e.g. # of these records > 0)
ID, Url, DOB
1, site1.com/page1, "5/06/2012 20:01"
2, site2.com/page2, "5/06/2012 21:20"
3, site1.com/page1, "6/06/2012 10:05"
If "now" is 6/06/2012 10:40 - I see that there was 1 new record (id=3) inserted but I don't want to generate an alert because we have seen this URL before (id=1).
if we have
4, site3.com/pageX, "6/06/2012 10:08"
then I want to generate an alert (return count=1) because this row was inserted in the last hour and we haven't seen it before.
What is the best way to implement it? ideally without nested queries
I think this is what you are after. This will retrieve new entries in the last hour (Where new means the same URL has not been visited unitl the last hour)
SELECT *
FROM Log
WHERE DOB > DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
AND NOT EXISTS
( SELECT 1
FROM Log T1
WHERE T1.URL = Log.URL
AND T1.DOB < DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
)
Working example on SQL Fiddle
EDIT
Just seen a comment that you only need a count:
SELECT COUNT(*)
FROM Log
WHERE DOB > DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
AND NOT EXISTS
( SELECT 1
FROM Log T1
WHERE T1.URL = Log.URL
AND T1.DOB < DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
)
EDIT 2
I am not sure why there is the requirement of only being a single select, however, the closest I can get to a single select is this:
SELECT COUNT(*)
FROM ( SELECT *, MIN(DOB) OVER(PARTITION BY URL) [FirstViewed]
FROM Log
) Log
WHERE FirstViewed >= DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
This will still return 2 if the same page has been visited twice in the last hour.
http://sqlfiddle.com/#!3/5a8bc/1
This one does something alternative, first search unique url by grouping, then extract those in the last hour.
SELECT x1.*
FROM
(SELECT URL,
COUNT(ID) AS urlcount,
MAX(DOB) AS uniqueurl
FROM Log
GROUP BY URL HAVING count(ID) = 1
OR MIN(DOB) > dateadd(HOUR ,-1 , CURRENT_TIMESTAMP)) AS x1
WHERE x1.uniqueurl > dateadd(HOUR ,-1 , CURRENT_TIMESTAMP);
http://sqlfiddle.com/#!3/250e0/45/0
I cannot figure out if this has acceptable performance without looking at an explain, but i think the sort operation involved in the group by could be a bottleneck
Without nested query (SQLFiddle):
SELECT COUNT(DISTINCT T0.URL)
FROM Log AS T0
LEFT OUTER JOIN Log AS T1 ON
T1.URL = T0.URL
AND T1.DOB < DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
WHERE
T0.DOB > DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
AND T1.ID IS NULL
But it really is the same solution as GarethD, performance wise.
Try this:
SELECT DISTINCT a.id, a.url, a.dob
FROM Log a JOIN Log b ON (a.url = b.url)
WHERE UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(a.DOB)<=3600
AND UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(b.DOB)>3600;
It should return all the records that follow the pattern you specified in the question.
Observe that I use UNIX_TIMESTAMP to get the dates translated to seconds, so the substract will return a difference in time expressed as an amount of seconds. And the comparison must be made against 3600 seconds.
EDIT:
The sentence has been corrected. But it's for MySQL (I didn't see the sql-server2005 tag)
select distinct(a.url) from tbl a, tbl b where a.dob>(now-hour) and b.dob<=(now-hour) and a.url=b.url;
(replace time manipulation with something from your db of choice. index the urls and dob)
Also hope that your database is sensible enough to do the dob-comparison before join and join using indexes.