SQL - Syntax for data within X number of days pulls all data - sql

I have a query I need to run regularly which pulls errors from a log table for x number of days. I originally found the syntax for the x number of days on here highlighted below with --<<.
The script pulls the information I want, throws no errors, but it pulls items from all dates not just past X days I am looking for. No matter what value I place before ...,getdate()) it pulls all the records.
Any Ideas how to get it to correctly give me the date range from today that I am looking for?
SELECT
t2.[campaignshortname],
t1.[CampaignId],
t1.[CreatedDtTm],
t1.[Msg],
t1.[ReferenceDate]
FROM
[alchemy].[CM].[CampaignLog] AS t1 (nolock)
INNER JOIN
[alchemy].[CM].[Campaign] AS t2 ON t1.CampaignId = t2.Id
WHERE
CAST(t1.[ReferenceDate] AS DATE) <= dateadd(DAY, -30, getdate()) --<<
AND t1.Msg LIKE '%fail%' OR t1.Msg LIKE '%error%'
ORDER BY
ReferenceDate DESC

I would actually change the query a little bit more and use between:
where convert(datetime, t1.[ReferenceDate]) between getdate()-30 and getdate()
and (t1.Msg like '%fail%' or t1.Msg like '%error%')
Although those to likes will cause a full scan of either index or table unless you subquery it.

You need to enclose your t1.Msg like '%fail%' or t1.Msg like '%error%' in parentheses, as and precedes or in execution order. As is, your condition searches in your table first rows where the date is 30 days or more before current date and message contains the word "fail", and then it searches in your table the rows where the message contains the word "error". Your condition then should be:
where CAST(t1.[ReferenceDate] AS DATE) <= dateadd(DAY, -30,getdate())
and (t1.Msg like '%fail%' or t1.Msg like '%error%')

Related

Using the result of a query to determine a value in a where clause in SQL?

So basically I've got a query where I want to filter using a date, however that date may change depending on what datas in the system.
If there's no records with a date of >='X', I want to use >='Y' instead
Currently I've got something like the following mess (Pseudocoded down to avoid using actual table names and such)
With a as (SELECT
count(column_id) as num
FROM tableA
WHERE ADate >= getdate() - 8)
,
b as (SELECT
case when num = '0' then getdate() - 15 else getdate() - 8 end as DateToUseInQuery
from A)
SELECT *
FROM tableB
Bunch of joins to other tables
WHERE BDate >= DateToUseInQuery
The general idea being is if there's no records for the week beforehand, use 2 weeks beforehand
I tried using a query within the where clause like:
WHERE BDate >= (SELECT DateToUseInQuery FROM b)
But the query ran for 11 minutes before I stopped it (Up from about 18 seconds before I tried to put this extra bit in)
I've been thinking about trying to set a variable as the date, but I can't do it in a CTE, and when I do it after, it breaks everything else.
So basically:
Is there an easier way to do this than the cack-handed way I'm trying?
If my way is fine, how can I pass that date properly into the WHERE clause?
You could try something like this. I am using a nested select and case statement to determine the number of days.
There may be a prettier way, but this works.
SELECT COUNT(column_id) AS num FROM TableA
WHERE ADate >=
DATEADD(Day,
(SELECT
CASE
WHEN EXISTS(
SELECT 1 FROM TableA
WHERE ADate >= DATEADD(Day,-8,GETDATE()))
THEN -8
ELSE -15
END AS 'dt')
,GETDATE());

DATEPART function assigning

I have table who order a order today and yesterday (18,17)
I need to find those result .
select A.C_Name
from Customer_Table A
inner join
Order_Table O
On A.C_ID=O.C_ID
where DATEPART(DAY,Order_Date)=GetDATE() and
DATEPART(DAY,Order_Date)=GETDATE()-1
I didnt get result for above query .
If you want orders today and yesterday, then this should be sufficient:
where Order_Date >= dateadd(day, -1, cast(getdate() as date))
(This assumes no future order dates, which seems reasonable).
Your query is a mess for several reasons. datepart() returns an integer and you are comparing it to a date. Looking at just the "day" part of a date will not work on the first of the month. And, getdate() -- despite its name -- has a time component, so direct equality is inappropriate.

Querying result from select part of statement

I have a stored procedure to work out how many working days between two dates
select
casekey, LoginName, casestartdatedate,
dbo.CalcWorkDaysBetween(casestartdatedate, GETDATE()) AS 'WD'
from
Car_case with (nolock)
where
dbo.CalcWorkDaysBetween(casestartdatedate, GETDATE()) <= DATEADD(dd,DATEDIFF(dd, 0, GETDATE()), -60)
and CaseClosedDateDate is null
order by
CaseStartDateDate asc
In my select part of statement I want to show the number of working days between the case start date and today's date. This part is fine. But I only want to return cases where the 'working days' is 60 days or greater - I'm having trouble with this part of query. See my code above. not too sure why its not working. It's returning results less than and greater than 60 days making me realize I've gone wrong somewhere.
Any help would be appreciated!
If I understand correctly, you just need to fix the where condition:
select casekey, LoginName, casestartdatedate,
dbo.CalcWorkDaysBetween(casestartdatedate, GETDATE()) AS WD
from Car_case cc with (nolock)
where dbo.CalcWorkDaysBetween(casestartdatedate, GETDATE()) >= 60 and
CaseClosedDateDate is null
order by CaseStartDateDate asc;
Note: In your version you are comparing the result of the function (which is presumably an integer) to a date.

Joining multiple tables returning duplicates

I am trying the following select statement including columns from 4 tables. But the results return each row 4 times, im sure this is because i have multiple left joins but i have tried other joins and cannot get the desired result.
select table1.empid,table2.name,table2.datefrom, table2.UserDefNumber1, table3.UserDefNumber1, table4.UserDefChar6
from table1
inner join table2
on table2.empid=table1.empid
inner join table3
on table3.empid=table1.empid
inner join table4
on table4.empid=table1.empid
where MONTH(table2.datefrom) = Month (Getdate())
I need this to return the data without any duplicates so only 1 row for each entry.
I would also like the "where Month" clause at the end look at the previous month not the current month but struggling with that also.
I am a bit new to this so i hope it makes sense.
Thanks
If the duplicate rows are identical on each column you can use the DISTINCT keyword to eliminate those duplicates.
But I think you should reconsider your JOIN or WHERE clause, because there has to be a reason for those duplicates:
The WHERE clause hits several rows in table2 having the same month on a single empid
There are several rows with the same empid in one of the other tables
both of the above is true
You may want to rule those duplicate rows out by conditions in WHERE/JOIN instead of the DISTINCT keyword as there may be unexpected behaviour when some data is changing in a single row of the original resultset. Then you start having duplicate empids again.
You can check if a date is in the previous month by following clause:
date BETWEEN dateadd(mm, -1, datefromparts(year(getdate()), month(getdate()), 1))
AND datefromparts(year(getdate()), month(getdate()), 1)
This statment uses DATEFROMPARTS to create the beginning of the current month twice, subtract a month from the first one by using DATEADD (results in the beginning of the previous month) and checks if date is between those dates using BETWEEN.
If your query is returning duplicates, then one or more of the tables have duplicate empid values. This is a data problem. You can find them with queries like this:
select empid, count(*)
from table1
group by empid
having count(*) > 1;
You should really fix the data and query so it returns what you want. You can do a bandage solution with select distinct, but I would not usually recommend that. Something is causing the duplicates, and if you do not understand why, then the query may not be returning the results you expect.
As for your where clause. Given your logic, the proper way to express this would include the year:
where year(table2.datefrom) = year(getdate()) and
month(table2.datefrom) = month(Getdate())
Although there are other ways to express this logic that are more compatible with indexes, you can continue down this course with:
where year(table2.datefrom) * 12 + month(table2.datefrom) = year(getdate()) * 12 + Month(Getdate()) - 1
That is, convert the months to a number of months since time zero and then use month arithmetic.
If you care about indexes, then your current where clause would look like:
where table2.datefrom >= dateadd(day,
- (day(getdate) - 1),
cast(getdate() as date) and
table2.datefrom < dateadd(day,
- (dateadd(month, 1, getdate()) - 1),
cast(dateadd(month, 1, getdate()) as date)
Eliminate duplicates from your query by including the distinct keyword immediately after select
Comparing against a previous month is slightly more complicated. It depends what you mean:
If the report was run on the 23rd Jan 2015, would you want 01/12/2014-31/12/2014 or 23/12/2014-22/01/2015?

Getting Dates only less than a particular date using date functions

I have a table called tableA with TrasactionDate as one field. I have a particular date called myfixeddate (say it's 2014-03-08).
I want to get the TransactionDate within 4 months, but only before my fixed date myfixeddate ('2014-03-08') from the tableA. Say my query should give '2014-03-06','2014-03-05','2014-02-01',....
But when I use the following query :
SELECT TrasactionDate
FROM tableA
WHERE datediff(mm,Transdate,myfixeddate) < 4
It gives the TransactionDate in both ways (before and after). That means the result gave '2014-03-10','2014-03-18' with the wanted ones like '2014-03-05',....
Could you please tell me how to prevent this and what code I need to use to get the TransactionDate in one direction?
You may try like this:
Select TrasactionDate from tableA
where [TrasactionDate] between DATEADD(month, -4, myfixeddate) and myfixeddate