SQL Query Statement Return Different Results - sql

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()?

Related

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

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.

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 Week over Week query for given timeframe

I have a table that is used for support tickets. I am trying to create a query that shows a week over week breakdown (how many tickets were created) for the last 8 weeks.
I have a calendar table created already and I am trying to make use of this to create the query.
Example:
SELECT *
FROM dbo.Calendar
WHERE calendar_DT >= DATEADD(week, -8, GETUTCDATE() -1)
AND calendar_DT <= GETUTCDATE()
ORDER BY calendar_DT ASC
Here I have a basic query that gives me all of the dates within the last 8 weeks. From here, I am trying to group this data by week so that I have a weekStart, weekEnd and then a count of records created which I will join another table for.
I attempted to do this without a calendar table but it seems that if records didn't exist for a specific week then theres gaps in the results instead of a 0.
This was my original attempt. Its close to what I want for the end result. However, I am not sure where the null is coming from and its missing a 2 weeks of data where no requests were created during this time.
SELECT DATEADD(week, DATEDIFF(week, 0, createdDate), 0) [From],
DATEADD(week, DATEDIFF(week, 0, createdDate), 0) + 6 [To],
COUNT(DISTINCT reqID) newRequests
FROM dbo.support_tickets
WHERE createdDate >= DATEADD(week, -8, GETUTCDATE())
AND tool = 244
GROUP BY DATEDIFF(week, 0, createdDate) WITH ROLLUP
ORDER BY DATEDIFF(week, 0, createdDate)
Desired result looks like the image above, a total count of records created for each of the last 8 weeks.
Do I need to continue with the use of the calendar table or can it be done without it and still show the to/from even if theres no results for that week?
The NULL row is the result of your GROUP BY...WITH ROLLUP. That's the rollup. The newRequests value of 7 is the total of your other records.
If you want dates to be listed that aren't in your table, you'll need to get them from somewhere else, which is just what a calendar table is for. So you're actually in pretty good shape once you add that join.

Need to find out last 15 days record (each day which record are last inserted in my table )

Need Help
Lets say--I have a staging table, everyday record are inserted, there is column is T_CREATED, This column has date (ddmmyyy hh24miss) example “12/16/2014 11:47:14 AM”
My scenario was, I need to find out when is last record last 15 days. Which means each day(in 24 hr) which record are last inserted
Can I get suggestion here?
I know I have to use MAX(T_CREATED) but could not figure it out.
Thanks
Sohel
I am not sure about the syntax in Oracle, this code will return the latest T_CREATED for each day.
-- SQL Server
SELECT MAX(obj_ID) AS MaxID, CONVERT(DATE, T_CREATED) AS [Date]
FROM source_tbl
WHERE CONVERT(DATE, T_CREATED) > CONVERT(DATE, DATEADD(DAY, -15, GETDATE()))
GROUP BY CONVERT(DATE, T_CREATED)
ORDER BY CONVERT(DATE, T_CREATED) DESC
-- Oracle
SELECT MAX(T_CREATED) AS MaxID, TRUNC(T_CREATED) AS [Date]
FROM source_tbl
WHERE TRUNC(T_CREATED) > TRUNC(SYSDATE - 15)
GROUP BY TRUNC(T_CREATED)
ORDER BY TRUNC(T_CREATED) DESC

Each GROUP BY expression error in sql server

I am building a stored procedure in MS SQL SERVER 2012. I want to display average level of current day.
CREATE PROCEDURE [dbo].[AverageP]
#UserID INT
AS
BEGIN
SELECT DAY(GETDATE()), AVG(Level) AS AvgLevel
FROM tab1
WHERE UserID = #UserID
GROUP BY DAY(GETDATE())
END
But i got this error:
Msg 164, Level 15, State 1, Procedure AverageP, Line 9 Each GROUP BY
expression must contain at least one column that is not an outer
reference.
Please, help me to solve this error!
You want a where clause, not group by. Something like this:
BEGIN
SELECT CAST(GETDATE() as DATE), AVG(Level) AS AvgLevel
FROM tab1
WHERE UserID = #UserID AND
tabl.SOMEDATEFIELD >= cast(GETDATE() as DATE) and
tab1.SOMEDATEFIELD < cast(GETDATE() + 1 as DATE)
END
It's complaining because you're not grouping by anything that is in tab1, but by the day of the current date.
Note that Day() is the number of the current day, like today it's 22 because it's May 22nd. If you're looking to look for the average for all Fridays you'll want Weekday() instead.
You probably don't mean to group at all if you just want the average level for all 22nds of the month across the data in your tab1. Is there a date column in tab1 that you mean to get the day of, and then in the where column say that the day of getdate() equals the day of that date column?
Actually you should be able to run this without a group at all.
SELECT DAY(GETDATE()) as [Day], AVG(Level) AS AvgLevel
FROM tab1
WHERE UserID = #UserID
But as Gordon points out we think you just want to filter by day. Either way the grouping is superfluous.