I faced a problem with a SQL query. I have a table with 10 fields.
I need to create a query, which gets date by field ProductionYear(int) between 2 variables #startDate(int) and #endDate(int). Both of these variables are unnecessary. And I need to build a SQL query with following conditions:
If(#endDate = 0)
Select Id from MyTable where ProductionYear > #startDate
else
Select Id from MyTable where ProductionYear BETWEEN #startDate and #endDate.
How can I build a query with those conditions?
You can incorporate this into a single query:
Select Id
from MyTable
where ProductionYear >= #startDate and
(ProductionYear <= #endDate or #endDate = 0);
Your two queries are inconsistent on whether #startDate is included. BETWEEN includes the comparison values, but > does not.
If you want #startDate to also be optional:
Select Id
from MyTable
where (ProductionYear >= #startDate or #startDate = 0) and
(ProductionYear <= #endDate or #endDate = 0);
Some additional comments. Calling a "year" a "date" is confusing. Your parameters should probably be called #startYear and #endYear.
These queries are going to result in full table scans of your table. This is probably not a big deal, because the granularity is by year. If the granularity were more refined, you might want to use an index. In that case, perhaps the best approach is dynamic SQL.
you can try by using case when
Select Id from MyTable
where ProductionYear BETWEEN (case when #startDate>#endDate then #endDate
else #startDate end) and
(case when #startDate>#endDate then #startDate else #endDate end)
Related
I need to calculate how many days one set period contains in another set period. I have table with
create table #test
(
,project nvarchar(10),
startProjectDate date,
endProjectDate date)
insert into #test values
('EE43213','2021-12-31','2022-01-06') ,
('EE0211213','2022-01-09','2022-03-14'),
('EE53134','2022-02-18','2022-02-22')
I have parameters with dates (user input in the future)
DECLARE #startDate DATE = N'2021-12-16'
DECLARE #endDate DATE = N'2022-03-02'
For every project I need to calculate, how many days of their running time will be set on user chosen period and then * this count on some koeff.
I have case when in mind, if the whole project was in parameter-set period, I just find datediff between two project dates and * it.
case when (startProjectDate BETWEEN #startDate and #endDate)
and (endProjectDate BETWEEN #startDate and #endDate)
then DATEDIFF(day, startProjectDate , endProjectDate) + 1 * coeff else ...
But how to find an amount of days if they only partially set on this period?
Seems you just need a DATEDIFF and some CASE expressions here:
DECLARE #StartDate DATE = N'20211216',
#EndDate DATE = N'20220302';
SELECT project,
DATEDIFF(DAY, CASE WHEN startProjectDate < #StartDate THEN #StartDate ELSE startProjectDate END, CASE WHEN endProjectDate > #EndDate THEN #EndDate ELSE endProjectDate END) AS DaysInRange,
DATEDIFF(DAY,startProjectDate, endProjectDate) AS DaysInProject
FROM #test
WHERE startProjectDate <= #EndDate
AND endProjectDate >= #StartDate;
I have some data stored in SQL Server which contains dates (date datatype). I am currently using a BETWEEN clause to filter my records in dates range, something like this ...
SELECT
*
FROM
Report
WHERE
ReportDate BETWEEN '2016-08-01' AND '2017-08-01'
Is it possible to use BETWEEN and LIKE clause at the same time or something close to that so that whenever a user doesn't specify any dates he/she would be able to pull all the reports? So far the query below
SELECT
*
FROM
Report
WHERE
ReportDate BETWEEN '' AND ''
doesn't show any records at all. Is there a way of doing this ..?
Use NULL with a parameter... if no value is given for #startDate and #endDate then the default will be NULL for these parameters, and the second WHERE condition would be met, returning all records.
create proc myProc(#startDate datetime = null, #endDate datetime = null)
as
SELECT * FROM Report
WHERE
(ReportDate BETWEEN #startDate AND #endDate)
or
(#startDate is null and #endDate is null)
Also, if your field is a DATETIME then this blog by Aaron is well worth your read.
Also, this method means the user has to enter both or neither of the parameters. If that's not what you'd want just let us know.
I think the correct logic would be:
SELECT r.*
FROM Report r
WHERE (ReportDate >= #startDate OR #startDate IS NULL) AND
(ReportDate <= #endDate OR #endDate IS NULL);
This works when only one of the values is NULL.
Note:
I would go with Aaron Bertrand's advice and really use:
SELECT r.*
FROM Report r
WHERE (ReportDate >= #startDate OR #startDate IS NULL) AND
(ReportDate < DATEADD(day, 1, #endDate) OR #endDate IS NULL);
I am trying to reuse a query, instead of creating several scenarios. Basically I am getting a COUNT from a big table.
The question is: am I going to lose performance on the long run if I am using
SELECT COUNT(id) FROM [Documents] WHERE UploadDate > '1900/1/1' AND UploadDate < GETDATE()
Instead of a simple
SELECT COUNT(id) FROM [Documents]
Basically the 2 queries would return the same thing, because I want to return ALL the records in this case. But under some other circumstances, the date pair will use different parameters.
If you want the count based on some parameters, I do not think there will a significant difference, if you have an index defined on UploadDate. If you are using a stored procedure, it might look like the following:
CREATE PROCEDURE dbo.GetCount
(
#FromDate DATETIME2 = '1900-01-01',
#ToDate DATETIME2 = '9999-12-31',
-- other filters may come here
)
AS
BEGIN
SELECT COUNT(id)
FROM [Documents]
WHERE UploadDate > #FromDate AND #ToDate < #ToDate
END
GO
-- get all
EXEC dbo.GetCount
-- get from date
EXEC dbo.GetCount #FromDate = '2015-03-01'
-- to date
EXEC dbo.GetCount #ToDate = '2016-03-01'
-- both
EXEC dbo.GetCount #FromDate = '2015-03-01', #ToDate = '2016-03-01'
You can also try to obtain the minimum SQL to run, by creating a dynamic SQL:
CREATE PROCEDURE dbo.GetCount
(
#FromDate DATETIME2 = NULL,
#ToDate DATETIME2 = NULL
-- other filters may come here
)
AS
BEGIN
DECLARE #SQL NVARCHAR(4000) = N'
SELECT COUNT(id) FROM [Documents]
WHERE 1 = 1
'
IF (#FromDate IS NOT NULL) #SQL = #SQL + ' UploadDate > #FromDate'
IF (#ToDate IS NOT NULL) #SQL = #SQL + ' UploadDate > #ToDate'
EXECUTE sp_executesql #SQL, '#FromDate DATETIME2, #ToDate DATETIME2', #FromDate, #ToDate
END
This offers the flexibility of open interval to the left and/or right.
If you are dynamically generating queries from the application layer (e.g. LINQ2SQL), the best option is generate it based on your parameters. This will lead to the shortest and fastest queries:
var query = DbContext.Documents;
if (fromDate.HasValue) query = query.Where(UploadDate > fromDate.Value);
if (toDate.HasValue) query = query.Where(UploadDate < toDate.Value);
int count = query.Count();
The last two solutions also allow to easily add new filters.
If you want to count everything and then things that meet a condition:
SELECT COUNT(id) as total_cnt,
SUM(CASE WHEN UploadDate > '1900-01-01' AND UploadDate < GETDATE()
THEN 1 ELSE 0
END) as specific_cnt
FROM [Documents] d;
If you're worried about varying performance based on the range values you specify in your query, because of parameter sniffing, then you can add OPTION (RECOMPILE) at the end of your query.
SELECT COUNT(id)
FROM [Documents]
WHERE UploadDate > '1900/1/1' AND UploadDate < GETDATE()
OPTION (RECOMIPLE)
This will make sure that your newly generated plan is the best possible that the Optimizer could come up with, at that moment, on its own, for that date range, if you decide to check starting from '2011/1/1' for example.
how can i use greater than equal to and less than equal to instead of using between in SQL
I'm checking for date variable in sql
i tried like this.
Date between coalesce(#fromDate,Date) and coalesce(#toDate,Date)
but if user does not enter any of date (fromDate or toDate)
so that I need to convert above condition in greater than equal to and less than equal to
please help in syntax in sql.
thanks
IF #fromDate IS NULL
BEGIN
SET #fromDate = '1900-01-01';
END;
IF #toDate IS NULL
BEGIN
SET #toDate = '2099-01-01';
END;
SELECT things
FROM table
WHERE date_field BETWEEN #toDate AND #fromDate;
This code will essentially give you an arbitrarily large range to check which should give you reasonable performance and return all results (assuming that's what you want when neither value is supplied).
This code can be shortened to:
SELECT things
FROM table
WHERE date_field BETWEEN Coalesce(#toDate, '1900-01-01') AND Coalesce(#fromDate, '2099-01-01');
But I kept the verbose version to illustrate.
Try this
SELECT Date FROM TableName WHERE Date > #fromDate AND Date < #toDate
SELECT *
FROM dbo.Account AS a
WHERE 1 = 1
AND (
#toDate IS NULL
OR a.CreateDate <= #toDate
)
AND (
#fromDate IS NULL
OR a.CreateDate >= #fromDate
)
Please note the 1 = 1 is only there to make the conditions clear and is by no means needed.
This should be what the where clause would look like.
Where
Date >= #fromDate
And
Date <= #toDate
I have a table which I want to query records from based on a timescale between two dates.
I have two variables,
DECLARE #StartDate datetime;
DECLARE #EndDate datetime;
What clause could I add to only show the records found within dates applied to these two variables?
This is based on a 'Date' column within the table.
SELECT myColumn
FROM myTable
WHERE Date BETWEEN #StartDate AND #EndDate
Edited: Between clause is inclusive (both dates are included in the result) so if you maybe want to exclude one of the dates in the variable columns better use:
SELECT myColumn
FROM myTable
WHERE Date >= #StartDate
AND Date <= #EndDate
SELECT * FROM [your_table] WHERE Date>=#StartDate AND Date<=#EndDate