How To group by date without time sql C# - c#

Hi when i trying to select the date I get also the time, but I need to do group by date without the time.
I also tried this: GROUP BY CAST(Orders.DatePlacing AS DATE), and I tried Convert , DATE(Orders.DatePlacing) and I tried this its not working for me.
Microsoft.ACE.OLEDB.12.0
public Product[] ProfitPrice(DateTime minDate, DateTime maxDate)
{
maxDate=maxDate.AddDays(1);
DataSet ds = new DataSet();
ArrayList products = new ArrayList();
string cmdStr = "SELECT Sum(((Products.PriceSell - Products.Price) * OrdersDetails.ProductCount)) AS Expr1,Orders.DatePlacing FROM Products " +
"INNER JOIN(Orders INNER JOIN OrdersDetails ON Orders.OrderId = OrdersDetails.OrderId) " +
"ON Products.ProductID = OrdersDetails.ProductId WHERE [Orders.DatePlacing] BETWEEN #" + minDate.ToString("yyyy-MM-dd") + "#" + "AND" +
" #" + maxDate.ToString("yyyy-MM-dd") + "# "+
"GROUP BY Orders.DatePlacing";
using (OleDbCommand command = new OleDbCommand(cmdStr))
{
ds = GetMultipleQuery(command);
}
DataTable dt = new DataTable();
try
{
dt = ds.Tables[0];
}
catch { }
foreach (DataRow tProduct in dt.Rows)
{
StatisticsFillArray(tProduct, products);
}
return (Product[])products.ToArray(typeof(Product));
}
private void StatisticsFillArray(DataRow tProduct, ArrayList products)
{
Product productsData = new Product();
productsData.PriceTotal = Convert.ToDouble(tProduct[0].ToString());
productsData.EntryDate = tProduct[1].ToString();
products.Add(productsData);
}

Accordingly to my comment to the question...
your code is sql injection vulnerable!
Do NOT use concatenated string, use parameterized queries instead.
Use table/column aliases!
To reject time part from datetime column, use DateSerial function
How? Take a look at below code:
string sql = #"SELECT Sum(((p.PriceSell - p.Price) * od.ProductCount)) AS Expr1, DateSerial(Year(o.DatePlacing), Month(o.DatePlacing), Day(o.DatePlacing)) DatePlacing
FROM Products p
INNER JOIN(Orders o INNER JOIN OrdersDetails od
ON o.OrderId = od.OrderId)
ON p.ProductID = od.ProductId
WHERE DateSerial(Year(o.DatePlacing), Month(o.DatePlacing), Day(o.DatePlacing)) BETWEEN #mindate AND #maxdate
GROUP BY DateSerial(Year(o.DatePlacing), Month(o.DatePlacing), Day(o.DatePlacing))";
DataTable dt = new DataTable();
using (OleDbConnection oConn = new OleDbConnection(yourConnectionStringHere))
{
oConn.Open();
using (OleDbCommand oComm = new OleDbCommand(yourCommandHere, oConn))
{
oComm.Parameters.Add(new OleDbParameter(){"#mindate", OleDbType = OleDbType.Date, Value = minDate},);
oComm.Parameters.Add(new OleDbParameter(){"#maxdate", OleDbType = OleDbType.Date, Value = maxDate},);
using (OleDbDataReader oRdr = oComm.ExecuteReader())
dt.Load(oRdr);
}
}

Related

SQL Query is correct, yet does not fill Data Table

I am attempting to fill a datatable with the following query:
SELECT
recipes.Name, Instructions, recipes.Preperation_Time, Author
FROM
RecipeIngredients
INNER JOIN
recipes ON recipes.Recipe_ID = RecipeIngredients.Recipe_ID
INNER JOIN
Ingredients ON Ingredients.Ingredient_ID = RecipeIngredients.Ingredient_ID
WHERE
ingredients.Name IN ('eggs')
When I run this query inside an .sql file I get the desired results:
However, when I attempt to fill a datatable with the query, I do not get any results. This is not an issue with my database nor the code as when I use a simple query, such as:
"Select * FROM recipes"
I get all recipes inside my datagridview:
Am I missing something here?
Here is my code for the form and the Database connections class.
private void resultsWindow_Load(object sender, EventArgs e)
{
// Format ingredient array for SQL Syntax
for(int i = 0; i< ingredientCount; i++)
{
string ing = ingredientArray[i];
string editedIng = "'" + ing + "'";
ingredientArray[i] = editedIng;
}
string ingredientString = string.Join(", ", ingredientArray);
// get connection string
string connectionString = Properties.Settings.Default.ConnectionString;
DataTable recipeDataTable = new DataTable();
conn = new DatabaseConnections(connectionString);
conn.openConnection();
// Get datatable
recipeDataTable = conn.getRecipes(ingredientString);
// Display data in grid view
recipesDataGrid.DataSource = recipeDataTable;
recipesDataGrid.Refresh();
}
public DataTable getRecipes(string ingredientString)
{
string sqlString = ("SELECT recipes.Name, Instructions, recipes.Preperation_Time, Author FROM RecipeIngredients" +
" INNER JOIN recipes ON recipes.Recipe_ID = RecipeIngredients.Recipe_ID" +
" INNER JOIN Ingredients ON Ingredients.Ingredient_ID = RecipeIngredients.Ingredient_ID" +
" WHERE ingredients.Name IN ('eggs')");
string sqlString_ = ("Select * FROM recipes");
DataTable recipeDataTable = new DataTable();
openConnection();
SqlCommand cmd = new SqlCommand(sqlString_, connectionToDB);
SqlDataAdapter da = new SqlDataAdapter(cmd);
// Fill dataset
da.Fill(recipeDataTable);
closeConnection();
return recipeDataTable;
}
I didn't try your code, but probably you just added the data in the table and it's not yet validated.
Could you try this statement in your T-SQL editor:
COMMIT TRANSACTION;

Loop on each item of a dataRow and group them by a primary key column

I am returning a dataRow from SQL server that contains appointments: Subject, Starting date, Ending date and Channel id.
I need to loop on each item of the dataRow to be able to group the items of a specific channel id in a separately to be able to add them to ultraGanttView.
The following code is working correctly to bind the data to a UltreMonthViewSingle.
So what i need to be able to bind the data in a ganttView is to group them by project which is the channel id in my case.
private void FillCalendar()
{
string query = #"select rs.[Planned Date in] as pdin,rs.[Planned Date out] as pdout, CONCAT(cn.Name,' ',ps.[First Name],' ',ps.[Last Name]) as subj, cn.[ID]
from [dbo].[Reservations] rs
inner join [dbo].[Person] ps on rs.[Person ID] = ps.ID
inner join [dbo].[Channel] cn on rs.[Channel ID] = cn.ID";
SqlConnection conn = new SqlConnection(Utilities.ConnectionString);
conn.Open();
//return reservations datatable
DataTable table = new DataTable();
SqlDataAdapter adp2 = new SqlDataAdapter(query, conn);
adp2.Fill(table);
//bind appointments
Appointment appointment;
DateTime dateIn, dateOut;
String subj;
foreach (DataRow dataRow in table.Rows)
{
dateIn = DateTime.Parse(dataRow["pdin"].ToString());
dateOut = DateTime.Parse(dataRow["pdout"].ToString());
dateIn.ToString("dd-MMMM-yyyy");
subj = dataRow["subj"].ToString();
appointment = this.ultraCalendarInfo1.Appointments.Add(dateIn, dateOut, subj);
}
}
What should i add to the loop so it can work?
This is a documentation how to bind data in ganttView GanttView Binding
Thank you
This is what i have done and it is working.
private void BindGantt()
{
this.ultraGanttView1.CalendarInfo = this.ultraCalendarInfo1;
string query = "select rs.[Channel ID],c.Name from[dbo].[Reservations] rs inner join[dbo].[Channel] c on rs.[Channel ID] = c.ID group by rs.[Channel ID],c.Name";
DataTable dt = new DataTable();
DataTable dc = new DataTable();
SqlConnection conn = new SqlConnection(Utilities.ConnectionString);
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = query;
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
DateTime dateFrom;
TimeSpan duration;
string subject;
int id;
//get the channels' id that have reservations
for (int j = 0; j < dt.Rows.Count; j++)
{
id = Convert.ToInt32(dt.Rows[j].ItemArray[0].ToString());
dc = GetChannelsReservations(id);
//get the info of all the reservations for a channel
ultraCalendarInfo1.Tasks.Add(DateTime.Now, TimeSpan.FromDays(0), dt.Rows[j].ItemArray[1].ToString());
for (int i = 0; i < dc.Rows.Count; i++)
{
dateFrom = Convert.ToDateTime(dc.Rows[i].ItemArray[0]);
TimeSpan.TryParse(dc.Rows[i].ItemArray[1].ToString(),out duration);
subject = dc.Rows[i].ItemArray[2].ToString();
ultraCalendarInfo1.Tasks[j].Tasks.Add(dateFrom, duration, subject);
}
}
}
private DataTable GetChannelsReservations(int id) {
string query = #"select rs.[Planned Date in],DATEDIFF(DAY, rs.[Planned Date in],rs.[Planned Date out]) as TimeSpan,c.Name+' '+p.[First Name]+' '+p.[Last Name],c.Name
from[dbo].[Reservations] rs
inner join[dbo].[Channel] c on rs.[Channel ID] = c.ID
inner join[dbo].[Person] p on rs.[Person ID] = p.ID
where rs.[Channel ID] ="+id;
DataTable dt = new DataTable();
SqlConnection conn = new SqlConnection(Utilities.ConnectionString);
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = query;
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
return dt;
}

SQL query return List

I can't seem to get this working:
My table column headers are 'genre' 'artist' 'album'
and the params I'm passing in are (type, filter, value) ("artist", "genre", "Rock") where there are two rows in the db with "Rock" for the genre.
When I follow the debugger, the 'while (reader.Read())' must return false because the loop is never entered and thus nothing written to the List.
public static List<String> getWithFilter(String type, String filter, String value)
{
List<String> columnData = new List<String>();
string query = "SELECT #type FROM Music WHERE" +
" #filter = '#value'";
SqlConnection connection = Database.GetConnection();
SqlCommand getData = new SqlCommand(query, connection);
getData.Parameters.AddWithValue("#type", type);
getData.Parameters.AddWithValue("#filter", filter);
getData.Parameters.AddWithValue("#value", value);
connection.Open();
using (connection)
{
using (getData)
{
using (SqlDataReader reader = getData.ExecuteReader())
{
while (reader.Read())
{
columnData.Add(reader.GetString(0));
}
}
}
}
return columnData;
}
You cannot use parameters for the names of columns and you don't put quotes around them when using them. Right now your query is the equivalent of
SELECT 'artist' FROM Music WHERE 'genre' = '#value'
You can do the following instead.
string query = "SELECT " + type + " FROM Music WHERE " + filter + " = #value";
And just remove the lines that create the #type and #fitler parameters.
You're looking either for formatting or string interpolation (requires C# 6.0):
string query =
$#"SELECT {type}
FROM Music
WHERE {filter} = #value";
...
getData.Parameters.AddWithValue("#value", value);
Formatting is a bit more wordy:
string query = String.Format(
#"SELECT {0}
FROM Music
WHERE {1} = #value", type, filter);
I assuming that you're using .net 2
DateTime current = DateTime.Now;
Console.WriteLine(current);
SqlConnection conn = new SqlConnection();
string q = "SELECT #field FROM student";
SqlDataAdapter da = new SqlDataAdapter(q, conn);
da.SelectCommand.Parameters.AddWithValue("#field", "snName");
DataTable dt = new System.Data.DataTable();
conn.Open();
da.Fill(dt);
conn.Close();
List<string> names = new List<string>();
foreach (DataRow dr in dt.Rows)
{
names.Add(dr[0].ToString());
}
Console.WriteLine("Fetching {0} data for {1}", names.Count, DateTime.Now - current);
Console.ReadKey();
You can use lambda expression to mapping the datatable in .net >4

Writing a SQL statement based on the values selected in a checkboxlist

I have two checkbox lists, one for a division and one for a course. One division can have many courses so what I want to do is have my user select whichever divisions they want as there are only 10 then display the courses in another checkbox list which are offered by the divisions that have been selected.
Precursor info:
private DataTable GetData(string query)
{
string constr = ConfigurationManager.ConnectionStrings["DatabaseName"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = query;
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataSet ds = new DataSet())
{
DataTable dt = new DataTable();
sda.Fill(dt);
return dt;
}
}
}
}
}
This is my code where I bind the data to the Divisions checkbox list:
protected void GetDiv()
{
string query = " Select distinct uio.OFFERING_ORGANISATION as [Div], ou.FES_FULL_NAME as [Division] From UNIT_INSTANCE_OCCURRENCES uio " +
" inner join ORGANISATION_UNITS ou on uio.OFFERING_ORGANISATION = ou.ORGANISATION_CODE " +
" inner join REPORTYEARS ry on uio.CALOCC_OCCURRENCE_CODE = ry.CAL_OCC " +
" Where ry.REPORT_YEAR = (select DETAILS from EF_REFERENCE_DATA Where REC_TYPE = 'Rep_Year') and uio.OFFERING_ORGANISATION is not null Order By [Division] ";
cbDivSelect.DataSource = GetData(query);
cbDivSelect.DataTextField = "DIVISION";
cbDivSelect.DataValueField = "DIV";
cbDivSelect.DataBind();
}
I use this to get a list of the divisions selected:
protected void cbDivSelect_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (ListItem item in cbDivSelect.Items)
{
if (item.Selected) Divisions.Add(item);
}
}
and then this to display the Courses:
protected void GetCourse()
{
foreach(ListItem item in Divisions)
{
string GetCourses = "SELECT distinct Course_Code,Course_Code + ' - ' + Marketing_Title AS COURSE, Parent FROM e_prospectus WHERE (Div = '" + item.Value.ToString() + "') ORDER BY Course_Code";
cbCourseSelect.DataSource = GetData(GetCourses);
cbCourseSelect.DataTextField = "COURSE";
cbCourseSelect.DataValueField = "Course_Code";
cbCourseSelect.DataBind();
}
}
Now currently it only displays the lowest course in the list which has been selected, i'm assuming because i keep changing the data source and it doesn't accumulate but is there any way i can change my code to accommodate what i want? thanks
Create one DataTable as DataSource and Merge() the results of GetData() into it.
This would build the whole set in memory. Depending how many Courses you expect using FakeisMe approach of building one query to get all courses out of the database at once might be a lot faster.
string divisions = string.empty ;
foreach(ListItem item in Divisions)
{
divisions = divisions + item.Value.tostring() + ",";
}
if (divisions != string.empty)
{
divisions = divisions.Remove(divisions.Length -1, 1)
string GetCourses = "SELECT distinct Course_Code,Course_Code + ' - ' + Marketing_Title AS COURSE, Parent FROM e_prospectus
WHERE (Div in (" + divisions + ")) ORDER BY Course_Code";
cbCourseSelect.DataSource = GetData(GetCourses);
cbCourseSelect.DataTextField = "COURSE";
cbCourseSelect.DataValueField = "Course_Code";
cbCourseSelect.DataBind();
}

How to stop showing multiple times of data in datagridview while retrieving from database in c#

I'm working with win-forms.I have a datagridview which is loaded its data from 2 tables of SQL database And I want to load data to datagridview as the data to be shown only once.
Here dtp is datetimepicker,the query i wanted is s_no should be from dailyattendance
(later I increment the s_no value as if last S_no is 10 in the table increases its value to
11,12,13 and so on while data is loading to datagridview) table and remaining
columns should be from employee details.
When I use below code ,the datagridview is binding with many reputations,that I dont want
private void bindgrid()
{
try
{
dataGridView1.ColumnCount = 10;
ConnectionStringSettings consettings = ConfigurationManager.ConnectionStrings["attendancemanagement"];
string connectionString = consettings.ConnectionString;
using (SqlConnection cn = new SqlConnection(connectionString))
{
cn.Open();
string dtp = dateTimePicker3grd.Value.ToString("dd/MM/yyyy");
//in this query if use ON d.Employee_Id = e.Employee_Id query
// it is showing only equal values with no reputation,so i tried to ON d.Employee_Id != e.Employee_Id query then many reputations are occurring.I dont want this
string query = "SELECT d.S_No,e.Employee_id,e.Employee_name,e.image_of_employee
FROM dailyattendance d JOIN employee_details e
ON d.Employee_Id = e.Employee_Id where e.Employee_Id not in (select Employee_Id from dailyattendance where date = '" + dtp + "' ) ";
SqlCommand cmd = new SqlCommand(query, cn);
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
int maxSlNo = int.Parse(dt.Rows[dt.Rows.Count - 1]["S_No"].ToString());
maxSlNo++;
foreach (DataRow dtRow in dt.Rows)
{
dtRow["S_No"] = maxSlNo;
maxSlNo++;
}
dt.AcceptChanges();
dataGridView1.Columns[0].Name = "S_No";
dataGridView1.Columns[0].HeaderText = "S_No";
dataGridView1.Columns[0].DataPropertyName = "S_No";
dataGridView1.Columns[1].HeaderText = "Employee_id";
dataGridView1.Columns[1].Name = "Employee_Id";
dataGridView1.Columns[1].DataPropertyName = "Employee_id";
dataGridView1.Columns[2].Name = "Employee_name";
dataGridView1.Columns[2].HeaderText = "Employee_Name";
dataGridView1.Columns[2].DataPropertyName = "Employee_name";
dataGridView1.Columns[3].Name = "In_time";
dataGridView1.Columns[3].HeaderText = "In_time";
dataGridView1.Columns[4].Name = "Out_time";
dataGridView1.Columns[4].HeaderText = "Out_time";
dataGridView1.Columns[5].Name = "Date";
dataGridView1.Columns[5].HeaderText = "Date";
dataGridView1.Columns[6].Name = "Week_no_of_the_Month";
dataGridView1.Columns[6].HeaderText = "Week_no_of_the_Month";
dataGridView1.Columns[7].HeaderText = "Attendance";
dataGridView1.Columns[7].Name = "Attendance";
dataGridView1.Columns[8].Name = "Work_status";
dataGridView1.Columns[8].HeaderText = "Work_status";
dataGridView1.Columns[9].Name = "Remarks";
dataGridView1.Columns[9].HeaderText = "Remarks";
// for Image_Of_employee I did not give column but automatically displaying in datagridview last column's cells
dataGridView1.DataSource = dt;
}
}
}
}
catch(Exception e1)
{
MessageBox.Show(e1.Message);
}
}
I called this method in form load()
Replace
string query = "SELECT d.S_No,e.Employee_id,e.Employee_name,e.image_of_Employee
FROM dailyattendance as d,employee_details AS e where e.Employee_Id
not in (select Employee_Id from dailyattendance where date = '" + dtp + "' )
Order By d.S_No";
with
string query = "SELECT DISTINCT d.S_No,e.Employee_id,e.Employee_name,e.image_of_Employee
FROM dailyattendance d JOIN employee_details e ON d.Employee_Id = e.Employee_Id
not in (select Employee_Id from dailyattendance where date = '" + dtp + "' )
Order By d.S_No";
You select data from 2 tables, but you didn't join tables. You ought to change the part of your query from
FROM dailyattendance as d,employee_details AS e
to
FROM dailyattendance d JOIN employee_details e ON d.Employee_Id = e.Employee_Id

Categories