简体   繁体   中英

c#, build sql to select a user given an age range

I have a talent table holding all my users with a column holding their birthdays. what would be the best way Talent within a specified age range. Here's what I have, but is seems to be off by a couple days. is there a better way?

// BUILD SQL FROM FORM DATA
sqlString += "SELECT * from Talent";

if (minAge != 0 || maxAge != 120)
{
     // The age criteria has been change, filter by age.

     // select all talents that have birthdays between the following 2 dates.
     DateTime startDate = (DateTime.Now - new TimeSpan((maxAge * 365), 0, 0, 0));  // maxAge * 365 = totalDays
     DateTime endDate = (DateTime.Now - new TimeSpan((minAge * 365), 0, 0, 0));
     sqlString += " WHERE Birthdate BETWEEN '" + startDate.ToString() + "' AND '" + endDate.ToString() + "'";
}

Assuming you're using SQL Server...

using (var connection = new SqlConnection(connString))
    using (var command = connection.CreateCommand()) {

        string tsql = @"
            select *
                from Talent
                where DATEDIFF(YEAR, BirthDay, GETDATE()) BETWEEN @minAge AND @maxAge";

        command.CommandText = tsql;
        command.CommandType = CommandType.Text;

        int minAge = 1;
        int maxAge = 120;

        SqlParameter minAgeParam = command.CreateParameter();
        minAgeParam.Direction = ParameterDirection.Input;
        minAgeParam.DbType = SqlDbType.TinyInt;
        minAgeParam.ParameterName = "@minAge";
        minAgeParam.Value = minAge;

        SqlParameter maxAgeParam = command.CreateParameter();
        maxAgeParam.Direction = ParameterDirection.Input;
        maxAgeParam.DbType = SqlDbType.TinyInt;
        maxAgeParam.ParameterName = "@maxAge";
        maxAgeParam.Value = maxAge;

        // Just unsure here whether I must add the parameters to the command,
        // or if they are already part of it since I used the 
        // SqlCommand.CreateParameter() method. 
        // Been too long since I haven't done any ADO.NET
        command.Parameters.Add(minAgeParam);
        command.Parameters.Add(maxAgeParam);

        connection.Open();

        SqlDataReader reader = null;

        try {
            reader = command.ExecuteReader();
            // Process your records here...
        } finally {
            connection.Close()
            command.Dispose();
            connection.Dispose();
            if (reader != null) {
                reader.Dispose();
            }
        }
    }

Where @minAge and @maxAge are your age parameters.

You may also tell the DATEDIFF TSQL function to consider the difference in days, in month, in hours, in minutes, in seconds, etc. Hence, you will have to convert your parameters value accordingly.

Personally, I've found using startDate.ToString("yy-MM-dd 00:00:00.000") and endDate.ToString("yy-MM-dd 23:59:59.000") works best (note the ,000 on the end date range. For some reason, in my experience, sql is off (probably due to some kind of rounding error) when it comes to ranges.

As an aside, you can use static methods from the TimeSpan object for time calculations. eg TimeSpan.FromDays(...)

The problem might be related to DateTime.Now , which considers time as well as date. Try replacing it with a DateTime.Today .

Why don't you use DateTime.AddYears method.

DateTime startDate = DateTime.Now.AddYears(-maxAge);

insated of

DateTime startDate = (DateTime.Now - new TimeSpan((maxAge * 365), 0, 0, 0)); 

Another thing is: Please don't use + operator between strings to build a sql query, use StringBuilder instead.

物有所值-您的原始解决方案将用几天的时间,因为它使用365而不是计算leap年。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM