SQL 2005 fetching data for current year - sql-server-2005

I have a view that holds sales data from 2012 till date, I need to write the query that show me only current year sales (2013).
This is what I tried in the first stage
SELECT *
FROM [Sales_Data]
WHERE invoiceDate between '2013-01-01' and '2013-12-31'
this query takes 2 sec to load the data,I though to change the query to fetch data that not required me to update it manually and this is what I found on the Net:
select * from [Sales_Data]
where datepart(yyyy,invoiceDate) =datepart(yyyy,getdate())
and datepart(yyyy,invoiceDate) =datepart(yyyy,getdate())
As a result this query takes much longer to show the data (9 sec).
Please let me know if there is a better query to define and get data in less time ?

Your second query requires sql server to perform a calculation for each row you are querying against.
The following query more closely matches your original select statement.
select * from [Sales_data]
where invoiceDate between DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0) --- First Day of current year
and DATEADD(MILLISECOND, -3,DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()) + 1, 0)) --- Last Day of current year
Depending on what is going on with the view you are querying against, you may also benefit from having an index which includes the invoiceDate field.
You may want to check the execution plan generated when you run your query to see what is going on behind the scenes when the query runs.

Related

SQL - Find value for the last 5 weeks and the next 5 weeks in the same query

I need to find inventory values for the last 5 weeks and the next 5 weeks on any given day I run the query (going to connect to Excel and run daily).
I am able to find them individually but when done together I get no returns.
The following work individually, is there a way to combine and get all returns?
Select * FROM Table
WHERE vdvInventory.Count >= CAST(DATEADD(WEEK, -5, GETDATE()) as DATE)
alternatively
Select * FROM Table
WHERE DATEDIFF(WEEK,vdvInventory.Count,GETDATE() )<5
If I try adding both where statements into one with an ADD I get no returns.
For Example:
Select * FROM Table
WHERE DATEDIFF(WEEK,vdvInventory.Count,GETDATE() )<5
AND DATEDIFF(WEEK,vdvInventory.Count,GETDATE() )>5
Thanks for any help or guidance with this!
Your query doesn't work because you have a contradictory statement: same expression (DATEDIFF(WEEK,vdvInventory.Count,GETDATE())) cannot be less and greater than 5 at the same time.
Try instead the following:
Select * FROM Table
WHERE vdvInventory.Count >= CAST(DATEADD(WEEK, -5, GETDATE()) as DATE)
and vdvInventory.Count <= CAST(DATEADD(WEEK, 5, GETDATE()) as DATE)

Different SQL query to compare date

I try to grab records from the email table which is less than 14 days. Just want to know if there is a performance difference in the following two queries?
select *
from email e
where DATEDIFF(day, e.recevied_date, cast(GETDATE() as date)) < 14
select *
from email e
where (GETDATE() - e.recevied_date) < 14
A sargable way of writing this predicate - ie, so SQL Server can use an index on the e.received_date column, would be:
where e.received_date > dateadd(day, -14, getdate())
With this construction there is no expression that needs to be evaluated for the data in the received_date column, and right hand side evaluates to a constant expression.
If you put the column into an expression, like datediff(day, e.received_date, getdate()) then SQL server has to evaluate every row in the table before being able to tell whether or not it is less than 14. This precludes the use of an index.
So, there should be virtually no significant difference between the two constructions you currently have, in the sense that both will be much slower than the sargable predicate, especially if there is an index on the received_date column.
The two expressions are not equivalent.
The first counts the number of midnights between the two dates, so complete days are returned.
The second incorporates the time.
If you want complete days since so many days ago, the best method is:
where e.received_date >= convert(date, dateadd(day, -14, getdate()))
The >= is to include midnight.
This is better because the only operations are on getdate() -- and these can actually be handled prior to the main execution phase. This allows the query to take advantage of indexes, partitions, and statistics on e.received_date.

SQL DATEADD Returning Incorrect Results

I'm currently writing a query for Visual Studio 2012 and testing it in Microsoft SQL Server Management Studio using SQL Server 2008 R2.
At the moment, I've read through MSDN's article on datetimes and DATEADD, but it seems like my syntax is right. I've also read some stuff on Google as well as How to select last one week data from today's date and MySQL: DATE_ADD as well as a few more Stack Overflow articles.
The query I'm running at the moment is really simple, just:
SELECT [DateTime] AS 'Time'
,[RawStatus] AS 'Data'
FROM [ADatabase].[dbo].[SomeTable]
WHERE CustomPollerAssignmentID = '6570267A-22E1-4556-B344-EB27D9831419' --Latency Poller
AND RowID = 000042 --Some Modem Number
AND DATEADD(HOUR, -1, CURRENT_TIMESTAMP) <= DateTime
ORDER BY DateTime DESC
What I was expecting this to do was to return the data (network latency in this case) for the last hour. Instead, it's returning the last three hours and thirty minutes. When running the code with the DATEADD statement commented out, it runs just fine and returns everything for the past day or two, the maximum time this table stores latency data.
Now, the strange code above is modeled after what's below, which I know works:
SELECT NMSDS.[SnapshotTimestamp] AS 'Time'
,[LatencyValue] AS 'Latency'
FROM [ADifferentDatabase].[dbo].[AnotherTable] Late
INNER JOIN ADifferentDatabase.dbo.YetAnotherTable NMSDS ON NMS_Id = 1
AND NMSDS.SnapshotID = Late.SnapshotID
WHERE DATEADD(HOUR, -6, CURRENT_TIMESTAMP) <= NMSDS.SnapshotTimestamp
AND InrouteGroupId = #IRID
AND NetworkId = #NTID
ORDER BY [Late].SnapshotID ASC
My questions are:
What am I missing?
Have I formatted my query wrong? And the second is why would it return 3.5 hours instead of one given the fact that the second query actually works and returns things properly?
I would have to say that you are missing timezone data.
From your queries, there is no data what timezone the servers are in, or what timezone they are inserting data to.
What exactly do you want?? Do you want the data for the last clock hour? (i.e., if it's 10:37 you want all data between 9:00 and 10:00)
or do you want the data for the past one hour? (i.e., if it's 10:37:12 you want all data between 9:37:13 and 10:37:12)
For the first, change the where clause to
...And NMSDS.SnapshotTimestamp >=
DateAdd(hour, datediff(hour, 0, Current_Timestamp)-1, 0),
And NMSDS.SnapshotTimestamp <
DateAdd(hour, datediff(hour, 0, Current_Timestamp), 0)
For the second, it's easier...
... And NMSDS.SnapshotTimestamp > Current_Timestamp - 1/24
but I admit I'm really confused by the value 6 in the second query... Why a 6, if you are trying for the data for the last single hour ??

To display only previous three months even the months before is not exist in database

Below is my new sql so far as i do not manage to use Dale M advice,
SELECT
all_months.a_month_id AS month,
year($P{date}) as year,
count(case when clixsteraccount.rem_joindate between DATE_FORMAT($P{date}-INTERVAL 2 MONTH, '%Y-%m-01') AND $P{date} THEN clixsteraccount.rem_registerbycn end) AS
total_activation,
'ACTIVATION(No)' AS fake_column
FROM clixsteraccount right join all_months on all_months.a_month_id = date_format(clixsteraccount.rem_joindate,'%m') and
(clixsteraccount.rem_registrationtype = 'Normal')and(clixsteraccount.rem_kapowstatus='pending' or clixsteraccount.rem_kapowstatus='success')
GROUP BY year,month
HAVING month BETWEEN month(date_sub($P{date},interval 2 month)) and month($P{date})
So, what i do is create a table with two fields, a_month_id(1,2,3...,12) and a_month(name of months). Sql above does give me what i want which is to display previous 3 months even the months before is not exist.
exp: data start on July. So, i want to display May,June and July data like 0,0,100.
The problem occur when it comes to next months or next year. When i try to generate sql based on parameter on Jan, it doesn't work like i thought. I do realize the problem are with 'Having' condition. Do anyone have idea how to improvised this sql to make it continue generate in the next,next year.
Thank you in advanced.
OK, I will make a few suggestions and give you an answer that will work on SQL Server - you will need to make any translations yourself.
I note that your query will aggregate all years together, i.e. Dec 2012 + Dec 2013 + Dec 2014 etc. Based on your question I don't think that is your intention so I will keep each distinct. You can change the query if that was your intention. I have also not included your selection criteria (other than by the month).
I suggest that you utilize an index table. This is a table stored in your database (or the master database if possible) with an clustered indexed integer column running from 0 to n where n is a sufficiently large number - 10,000 will be more than enough for this application (there are 12 months in a year so 10,000 represents 833 years). This table is so useful everyone should have one.
SELECT DATEADD(month, it.id, 0 ) AS month
,ISNULL(COUNT(clixsteraccount.rem_registerbycn), 0) AS registration
,'REGISTRATION(No)' AS fake_column
FROM cn
INNER JOIN ON ca.rem_registerbycn = cn.cn_id
clixsteraccount ca
RIGHT JOIN
IndexTable it ON it.id = DATEDIFF(month, 0, clixsteraccount.rem_joindate)
WHERE it.id BETWEEN DATEDIFF(month, 0, #StartDate) - 3 AND DATEDIFF(month, 0, GETDATE())
GROUP BY it.id
The way it works is by converting the clixsteraccount.rem_joindate to an integer that represents the number of months since date 0 (01-01-1900 in SQL Server). This is then matched to the id column of the IndexTable and limited by the dates you select. Because every number exists in the index table and we are using an outer join it doesn't matter if there are months missing from your data.

Select from table given day

So I have a table in SQL Server with a datetime column on it. I want to select all from this table:
select * from dbo.tblMessages
but I want to pass in a datetime parameter. Then I want to select all messages from the table that have the same day as the datetime column in tblMessages, not just ones posted in the past 24 hours, etc.
How would I do this?
Thanks.
This should use an index on MyDateTimeCol in tblMessages
select * from dbo.tblMessages
WHERE
MyDateTimeCol >= DATEADD(day, DATEDIFF(day, 0, #Mydatetimeparameter), 0)
AND
MyDateTimeCol < DATEADD(day, DATEDIFF(day, 0, #Mydatetimeparameter), 1)
Any function applied to MyDateTimeCol will prevent an index being used correctly, includin DATEDIFF between this and #Mydatetime
As you are on SQL Server 2008 you can just do
SELECT *
FROM tblMessages
WHERE CAST(message_date AS DATE) = CAST(#YourDateParameter AS DATE)
This is sargable. SQL Server will add a ComputeScalar to the plan that calls the internal GetRangeThroughConvert function and gets the start and end of the range to seek.
If you need to do this a lot, and if you're on SQL Server 2005 or newer, you could also do this:
add three computed columns for the day, month, year of your date and persist those
ALTER TABLE dbo.YourTable
ADD DayPortion AS DAY(YourDateTimeColumn) PERSISTED
-- do the same for MONTH(YourDateTimeColumn) and YEAR(YourDateTimeColumn)
put an index on the three columns:
CREATE NONCLUSTERED INDEX IX_DatePortions
ON dbo.tblMessages(YearPortion, MonthPortion, DayPortion)
now, you can search very easily and quickly for those days, months, year, and with the index, your search will be very performant and quick
SELECT (list of columns)
FROM dbo.tblMessages
WHERE YearPortion = 2011 AND MonthPortion = 4 AND DayPortion = 17
With this setup - three computed, persisted columns - you can now simply insert new rows into the table - those three columns will be calculated automatically.
Since they're persisted and indexed, you can easily and very efficiently search on those columns, too.
And with this flexibility, you can also easily find e.g. all rows for a given month or year very nicely.