I have the following code :
Connection c = new Connection();
string select1 =
#"SELECT
E.employeeNumber AS 'Employee Number',
E.employeePrivateName + ' ' + E.employeeFamilyName AS 'Employee Name',
DATEDIFF (MONTH, E.startWorkingDate, GETDATE()) AS 'Seniority in Month',
M.machineName AS 'Machine Name', J.jobName AS 'Job Name',
COUNT(E.employeeNumber) AS 'Number of Times on Machine in Specif Job',
SUM(Number_Of_Days_During_The_Period) AS 'Total Working Days on Machine in Specif Job',
SUM(Salary_per_Period) AS 'The Salary For working on Machine in Specif Job'
FROM
TblEmployee E
INNER JOIN
AllSchedules A_S on E.employeeNumber = A_S.employeeNumber
INNER JOIN
TblJob J on J.jobNumber = A_S.jobNumber
INNER JOIN
TblMachine M on M.machineNumber = A_S.machineNumber
INNER JOIN
TblPeriod P on P.Number = A_S.periodNumber
WHERE
Month(P.fromDate) = Month(#Month)
GROUP BY
E.employeeNumber, E.employeePrivateName, E.employeeFamilyName,
E.startWorkingDate, M.machineName, J.jobName
ORDER BY
E.employeeFamilyName , E.employeePrivateName";
SqlCommand cmd = new SqlCommand(select1, c.con);
DateTime month = comboBox1.Text;
cmd.Connection = c.con;
cmd.Parameters.AddWithValue("#Month", month);
SqlDataAdapter dataAdapter = new SqlDataAdapter(cmd); //c.con is the connection string
SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter);
DataSet ds = new DataSet();
dataAdapter.Fill(ds);
dataGridView1.ReadOnly = true;
dataGridView1.DataSource = ds.Tables[0];
I want to run the query, however I need to define a datetime value so it would be a search parameter for the query. How do I save the DateTime variable so that it will hold a month number (10 for october, etc.)
Thanks
In your query you have this line for the WHERE condition
WHERE Month(P.fromDate)= Month(#Month)
THe MONTH function of T-SQL expects to receive a Date for its parameter, so you probably need only
DateTime dt = new DateTime(DateTime.Today.Year, month, 1);
and pass this value for the parameter #Month
cmd.Parameters.AddWithValue("#Month", dt);
EDIT: If you have a combobox with items filled with the month names ordered: (January, February....)
// In array the indexes start at zero.....
if(cboMonths.SelectedIndex >= 0)
{
int month = cboMonts.SelectedIndex + 1;
}
You can use
string monthString = DateTime.ParseExact(comboBox1.Text, "MMMM", CultureInfo.CurrentCulture ).Month.ToString("MM");
and to convert it to an integer:
int month = int.Parse(monthString);
string sMonth = DateTime.Now.ToString("MM");
Given that the SQL Month function returns an integer (Source) you need to replace:
"... WHERE Month(P.fromDate)= Month(#Month) GROUP BY ..."
by
"... WHERE Month(P.fromDate) = " + intMonth.ToString() + " GROUP BY ..."
where intMonth is the integer value of the month selected from your combobox.
However, you will need to make sure that it is just an integer and can't be used as an injection attack. You would be better off putting all your SQL into a stored procedure and passing the month as an integer parameter.
Related
I have a DataGridView (calendarDGV) that is populated based off of data pulled from a database. I need to take two columns that contain DateTime values and convert them from UTC (which is how they're stored) to the local time of the user's machine.
I have other functions that convert times that are working properly, so I suspect that it has to do with how I'm pulling the data from the DGV.
I've tested that the string I'm making from the DGV cell value is holding the correct value, so beyond that I'm unsure why it is not being recognized as valid.
Here's how I'm populating the DGV as well as a loop that I am using to change the cell values.
private void generateCalendar()
{
MySqlConnection con = new MySqlConnection(Program.connectDB);
con.Open();
string query = "";
if (weekAppsRB.Checked)
{
query = $"SELECT a.appointmentId AS 'Appointment ID', a.type AS Type, DATE_FORMAT(a.start, \'%Y-%c-%d %T\') AS 'Start Time', DATE_FORMAT(a.end, \'%Y-%c-%d %T\') AS 'End Time', a.title AS Title, a.description AS Description, c.customerName AS 'Customer Name', a.location AS Location, a.contact as Contact FROM appointment a INNER JOIN customer c USING(customerId) WHERE YEARWEEK(start, 1) = YEARWEEK(CURRENT_DATE(), 1) AND a.userid = '{User.UserID}' ORDER BY start, 'Start Time'";
}
else if (monthAppsRB.Checked)
{
query = $"SELECT a.appointmentId AS 'Appointment ID', a.type AS Type, DATE_FORMAT(a.start, \'%Y-%c-%d %T\') AS 'Start Time', DATE_FORMAT(a.end, \'%Y-%c-%d %T\') AS 'End Time', a.title AS Title, a.description AS Description, c.customerName AS 'Customer Name', a.location AS Location, a.contact as Contact FROM appointment a INNER JOIN customer c USING(customerId) WHERE MONTH(start) = MONTH(CURRENT_DATE()) AND YEAR(start) = YEAR(CURRENT_DATE()) AND a.userid = '{User.UserID}' ORDER BY start, 'Start Time'";
}
MySqlCommand cmd = new MySqlCommand(query, con);
MySqlDataAdapter adp = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
adp.Fill(dt);
calendarDGV.DataSource = dt;
for (int i = 0; i < calendarDGV.Rows.Count; i++)
{
calendarDGV[2, i].Value = DateTimeHandler.toLocalTime(Convert.ToString(calendarDGV[2, i].Value));
}
}
And here is the function that I am getting an error at.
/*** Converts UTC time to Local time ***/
public static string toLocalTime(string dateTime)
{
DateTime utcTime = DateTime.Parse(dateTime.ToString()); //Error: String was not recognized as valid
DateTime localTime = utcTime.ToLocalTime();
return localTime.ToString("yyyy-MM-dd HH:mm:ss");
}
Note: The end users are not all in the same time zone, so local is specific to the machine that the program is running on.
Thanks in advance for any help/suggestions!
try thin in client-side (javascript)
function convertUTCDateToLocalDate(date) {
var newDate = new Date(date.getTime()+date.getTimezoneOffset()*60*1000);
var offset = date.getTimezoneOffset() / 60;
var hours = date.getHours();
newDate.setHours(hours - offset);
return newDate;
}
I have a stop watch and a database. I want to be able to report how much time in the whole database was recorded in total on a given date.
The x date is given by a datetimepicker.
When I click relative button in my C# program in order to sum up the time with my "SumOnDateReport" stored procedure, I get this error:
Additional information: Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
How I managed to do it:
record the time with stopwatch
save the label.text into the database
substring(devide) the text in 3 sections(hh:mm:ss)
convert them to integer
convert them to seconds (eg. hh*3600/ mm*60)
add them together
divide them by 60 to report them as minutes
your needed information:
My table(with pre-entered data):
id TimeSpanColumn TimeStampColumn TimeStringColumn TotalSecColumn
------------------------------------------------------------------
1 23:12:50 2011/07/12 12:00:00 NULL NULL
2 2:07:24 2012/03/09 12:00:00 NULL NULL
3 54:17:52 2013/03/09 12:00:00 NULL NULL
My addtime C# code (via stored procedure):
DateTime dateTime = DateTime.Today;
timer1.Stop();
sqlcon.Open();
SqlCommand sqlcmd = new SqlCommand("AddTime", sqlcon);
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.Parameters.AddWithValue("#QTimeSpan", label1.Text + ":" + label3.Text + ":" + label5.Text);
sqlcmd.Parameters.AddWithValue("#QTimeStamp", dateTime);
sqlcmd.Parameters.AddWithValue("#QTimeString", label1.Text + label3.Text + label5.Text);
sqlcmd.ExecuteNonQuery();
SqlDataAdapter sqlda = new SqlDataAdapter("GetSavedInfo", sqlcon);
DataTable dt = new DataTable();
sqlda.Fill(dt);
dataGridView1.DataSource = dt;
sqlcon.Close();
My addTime stored procedure:
CREATE PROCEDURE AddTime
#QTimeSpan NVARCHAR(50),
#QTimeStamp DATETIME,
#QTimeString NVARCHAR(50)
AS
INSERT INTO InfoTable (TimeSpanColumn, TimeStampColumn, TimeStringColumn)
VALUES (#QTimeSpan, #QTimeStamp, #QTimeString)
RETURN
My report on a date C# code:
SqlDataAdapter sqlda = new SqlDataAdapter("SumOnDateReport", sqlcon);
sqlda.SelectCommand.CommandType = CommandType.StoredProcedure;
sqlda.SelectCommand.Parameters.AddWithValue("#QueryDate", dateTimePicker1.Value.ToString("MM/dd/yyyy"));
DataTable dt = new DataTable();
sqlda.Fill(dt);
dataGridView2.DataSource = dt;
My SumOnDateReport stored procedure:
CREATE PROCEDURE SumOnDateReport
#QueryDate DATETIME
AS
DECLARE #total_sec INT
DECLARE #HourTime INT
DECLARE #MinTime INT
DECLARE #SecTime INT
SET #HourTime = (SELECT CONVERT(INT, SUBSTRING(TimeStringColumn, 1, 2))
FROM InfoTable
WHERE TimeStampColumn = #QueryDate)
SET #MinTime = (SELECT CONVERT(INT, SUBSTRING(TimeStringColumn, 3, 2))
FROM InfoTable
WHERE TimeStampColumn = #QueryDate)
SET #SecTime = (SELECT CONVERT(INT, SUBSTRING(TimeStringColumn, 5, 2))
FROM InfoTable
WHERE TimeStampColumn = #QueryDate)
SET #total_sec = #HourTime * 3600 + #MinTime * 60 + #SecTime
INSERT INTO InfoTable(TotalSecColumn)
VALUES (#total_sec)
SELECT TotalSecColumn
FROM InfoTable
WHERE TimeStampColumn = #QueryDate
You will get this error if you have more than one record in InfoTable with the same value in TimeStampColumn matching your value for #QueryDate. You will need to change those subqueries to ensure they return a single record. In this case I think you want to SUM those values.
set #HourTime = (select SUM(CONVERT(int,substring(TimeStringColumn,1,2)))
from InfoTable WHERE TimeStampColumn=#QueryDate)
set #MinTime = (select SUM(CONVERT(int,substring(TimeStringColumn,3,2)))
from InfoTable WHERE TimeStampColumn=#QueryDate)
set #SecTime = (select SUM(CONVERT(int,substring(TimeStringColumn,5,2)))
from InfoTable WHERE TimeStampColumn=#QueryDate)
I have a column in my database that holds a string on different week days for my contact.
For Example: Contact 1 works Monday and Wednesday.
So in the Week_Day column the string for Contact 1 is "Monday, Wednesday". I am trying to only show the rows who work on the current day of the week, the code is below. I tried using the IN clause, but it's not working because I don't have a set day of the week I want to filter. HELP!
string today = DateTime.Today.ToString("MM-dd-yy");
string day = DateTime.Today.DayOfWeek.ToString();
string find = "select convert(varchar(8), start, 10) AS start, convert(varchar(8), end_date, 10) AS end_date, ContactName, DepartmentName, Hours, Phone, Week_Day from Schedule join Contacts on Schedule.ContactId = Contacts.ContactId inner join Departments on Contacts.DepartmentId = Departments.DepartmentId where #Current BETWEEN start AND end_date AND Week_Day IN (#Day)";
SqlCommand comm = new SqlCommand(find, con);
comm.Parameters.Add("#Current", SqlDbType.Date).Value = today;
comm.Parameters.Add("#Day", SqlDbType.NVarChar).Value = day;
con.Open();
comm.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = comm;
DataSet ds = new DataSet();
da.Fill(ds);
GridView3.DataSource = ds;
GridView3.DataBind();
con.Close();
Well you can get the current day of week (name) like so:
string day = DateTime.Today.ToString("dddd");
Then you can use that in your WHERE query with a LIKE. Change your query to have:
WHERE Week_Day LIKE #day
And add you param for #day to include % at start and end:
comm.Parameters.Add("#Day", SqlDbType.NVarChar).Value = "%" + day + "%";
More info on LIKE here
NOTE: As some comments have already mentioned it would be better to not store the data this way in a single string column, but I have answered based on your question as it stands.
Perhaps with DateName() and CharIndex()
Where CHARINDEX(DateName(WEEKDAY,GetDate()),Week_Day)>0 and...
I am trying to sort my database data in datagridview using DateTimePicker control , the type of date column in my Event_test table is datetime2
SqlDataAdapter sda = new SqlDataAdapter("SELECT * from Event_test where date between '"
+dateTimePicker1.Value.ToString()+"' AND'"+dateTimePicker2.Value.ToString()+ "'", con);
DataTable data = new DataTable();
sda.Fill(data);
dataGridView1.DataSource = data;
This solution doesn't work properly , it sorts data wrongly at first time and when i change time pickers this error occurs :
Conversion failed when converting date and/or time from character
string
Any help is appreciated.
So how shall I adjust the select statement to get what I need?
Looks like dateTimePicker1 and dateTimePicker2
are both unchangeable ; they are set to 01/10/2016 and 10/10/2016 and whenever i change dates it shows me results between those dates !!
You really need to format your date string to match the format of SQL-Server:
string sqlFormat = "yyyy-MM-dd HH:mm:ss.fff";
String query = "SELECT * from Event_test where date between '"
+ dateTimePicker1.Value.ToString(sqlFormat) + "' AND'"
+ dateTimePicker2.Value.ToString(sqlFormat) + "'";
Better option is to use Sql Parameters (try to avoid query strings concatenation):
var sda = new SqlDataAdapter("SELECT * from Event_test where [date] between #p1 AND #p2", con);
SqlParameter dateParamFrom = new SqlParameter("#p1", SqlDbType.DateTime2);
dateParamFrom.Value = dateTimePicker1.Value;
SqlParameter dateParamTo = new SqlParameter("#p2", SqlDbType.DateTime2);
dateParamTo.Value = dateTimePicker2.Value;
sda.SelectCommand.Parameters.Add(dateParamFrom);
sda.SelectCommand.Parameters.Add(dateParamTo);
I have two datepickers whose dates are to be used in this query:
da = new SqlDataAdapter(#"
select * from TotalBill
where SaudaDate between
convert(datetime,'" + dtpForDate.Value.Date.ToString("MM/dd/yyyy") + "')
and convert(datetime,'" + dtpToDate.Value.Date.ToString("MM/dd/yyyy") + "')"
, con);
DataSet ds = new DataSet();
da.Fill(ds);
gvDailyBill.DataSource = ds.Tables[0];
When I want to query for one day, I cannot set both datepickers to the same day, but I have to set the From to the day I want and the To to a day beyond. If I don't, the query becomes something like this:
select * from totalbill where SaudaDate between '1/2/2013' and '1/2/2013'
Which of course returns 0 rows. How do I alter my code or query to allow the selection of the same day in the datepickers?
Important first :
You need parametrized query.
var fromDate = dtpForDate.Value.Date;
var toDate = dtpToDate.Value.Date;
string selectSQL = "select * from TotalBill where SaudaDate between #start and #end";
da = new SqlDataAdapter();
SqlCommand selectCMD = new SqlCommand(selectSQL, con);
da.SelectCommand = selectCMD;
selectCMD.Parameters.Add("#start ", SqlDbType.DateTime).Value = fromDate;
selectCMD.Parameters.Add("#end", SqlDbType.DateTime).Value = toDate;
DataSet ds = new DataSet();
da.Fill(ds);
gvDailyBill.DataSource = ds.Tables[0];
Secondly, you filter by date. But when your start date is equal to your end date, you want the datas of all the day.
What if the start date and the end date are different ? Do you want to include all the values of the end date too?
When you say "01/01/2010" to Sql, it understand "01/01/2010 00:00:00". You can't filter by date, but you filter by date*time*. This is an important difference.
So in your case, the right query is I think :
var fromDate = dtpForDate.Value.Date;
var toDate = dtpToDate.Value.Date.AddDays(1); // trick, add one day
In this case, when fromDate == toDate == '1/2/2013', you will get all the datas between '1/2/2013 00:00:00' and '1/3/2013' 00:00:00'. In pure english, you will get all the datas of the day 1/2/2013.
your Query must be like below...
"select * from TotalBill
where CONVERT(VARCHAR(10), SaudaDate, 101) between
convert(datetime,'" + dtpForDate.Value.Date.ToString("MM/dd/yyyy") + "')
and convert(datetime,'" + dtpToDate.Value.Date.ToString("MM/dd/yyyy") + "')"
SaudaDate is in Date time format.... So it may be like this '1/2/2013 07:54:00'
and if you convert this like CONVERT(VARCHAR(10), SaudaDate, 101) then it will become '1/2/2013 00:00:00'
Now it will give you the result you needed..
Try it...
If you wish to include the dates then dont use between. Use greater/less than or equal.
select * from totalbill where SaudaDate >= '2013-02-01' and SaudaDate <= '2013-02-01'
Edit. If your date column is actually a datetime which has times other than 00:00:00.000 then you will need to use the "Like" in your where for a single date.
select * from totalbill where SaudaDate like '2013-02-01%'
Or you will need to add a single day to the second date programatically.
select * from totalbill where SaudaDate >= '2013-02-01' and SaudaDate <= '2013-02-02'
You need to convert SaudaDate to only date part.
Try following:
try
{
da = new SqlDataAdapter(#"
select * from TotalBill
where Cast(Convert(varchar(20),SaudaDate,101) as Datetime) between
convert(datetime,'" + dtpForDate.Value.Date.ToString("MM/dd/yyyy") + "')
and convert(datetime,'" + dtpToDate.Value.Date.ToString("MM/dd/yyyy") + "')"
, con);
DataSet ds = new DataSet();
da.Fill(ds);
gvDailyBill.DataSource = ds.Tables[0];
}
catch (Exception ex){}
This code will work for the same day selection too.
Not tested,
You need to change your SQL query
select * from TotalBill
where SaudaDate >=#yourDateFrom
AND SaudaDate<=#yourDateTo