I am trying to allocate academy for student with only one click. This allocation need to have condition before allocating a specific academy to the student.
Here are my database tables:
tblAcademy
Acad_id name seat_available
------------------------------
1 A 2
2 B 2
3 C 1
4 D 5
5 E 3
tblStudent
stud_Id name `stud_purcentage` `stud_result` acad_id
----------------------------------------------------------
1 Alex 100 `Pass`
2 Lee 80.5 `Pass`
3 Lea 40.3 `Fail`
4 Loane 10 `Fail`
5 john 50 `Pass`
tblAcademy_selection
stud_id Acad_id order_preference
--------------------------------
1 1 1
1 3 2
4 3 1
4 2 2
4 4 3
Acad_id is foreign key of tblAcademy. The acad_id can remain null if the condition is not respected a student may do not have academy.
In the tblAcademy selection it shows that a student can select many academy but only one has to be allocate to them.
The allocation must be based on the seat available by the academy, on those who pass and allocate those from best percentage to the worst.
Till now I have been able to retrieve from the best to worst student and those who passed. I have then join those student id to the tblAcademy_selection.
SqlConnection dbcon = new SqlConnection(_conString);
SqlCommand scmd = new SqlCommand();
scmd.CommandText = "SELECT stud_Id, stud_fname, stud_purcentage, stud_totalMarks FROM tblStudent WHERE stud_result = 'Pass' ORDER BY stud_purcentage DESC";
scmd.Connection = dbcon;
SqlDataAdapter da = new SqlDataAdapter(scmd);
DataTable dt = new DataTable();
dbcon.Open();
da.Fill(dt);
string[] array = new string[dt.Rows.Count];
// foreach (DataRow row in dt.Rows)
for (int a = 0; a < dt.Rows.Count; a++)
{
// studID = row["stud_Id"].ToString();
array[a] = dt.Rows[a]["stud_Id"].ToString();
SqlCommand scmd2 = new SqlCommand();
scmd2.CommandText = "SELECT * FROM tblAcademy ta JOIN tblAcademy_Selection tas ON ta.acad_Id = tas.acad_Id WHERE stud_Id IN ('" + array[a] + "')";
scmd2.Connection = dbcon;
SqlDataAdapter da2 = new SqlDataAdapter(scmd2);
DataTable dt2 = new DataTable();
da2.Fill(dt2);
string[] array2 = new string[dt2.Rows.Count];
for (int a2 = 0; a2 < dt2.Rows.Count; a2++)
{
array2[a2] = dt2.Rows[a2]["stud_Id"].ToString();
SqlCommand scmd3 = new SqlCommand();
}
}
In my first SQL statement I have selected those who have best percentage and those whose who passed and stored in an array.
With the for loop I am retrieving the data table value
In the second SQL statement, I have made a join with tblAcademy and tblAcademy_selection where the tblAcademy_selection.stud_id is in the retrieve value that I have done in the first statement.
I am having difficulty to apply the condition in which if an student choice of academy seat is full it move to the second choice and if the second is full it move to the third and so on.
A student may not have academy if all his choice academy seat is full.
You have to apply a filter condition in your SQL statement to filter out records with tblAcademy.seat_available = 0.
Then generate a row_number or rank based on order preference and retrieve records with generated row_number =1.
Something like this:
SELECT * FROM
(
SELECT tas.*, DENSE_RANK() OVER (PARTITION BY stud_id ORDER BY order_preference) AS row_id
FROM tblAcademy ta
JOIN tblAcademy_Selection tas ON ta.acad_Id = tas.acad_Id
WHERE ta.seat_available >0 and stud_Id IN ('" + array[a] + "')"
) DTL
WHERE row_id = 1
Related
I have been working on this gridview project for a few days and have been able to make some progress. Where I am having difficulty is after sorting the gridview which works fine, I want to take the selected rows from my gridview and place those selected rows into a repeater control. I have been looking here for people with the same issue and have tried using viewstate but I continue to only get the default sort order into the repeater control. Example row 0 is selected with the name john smith after sort I have jane doe at row 0 but when selecting row 0 and jane doe I get john smith in the repeater control. I know that this has to be something simple but I have tried many things with not luck.
This is my sort code which works.
protected void GridView1_Sorting1(object sender, GridViewSortEventArgs e)
{
DataTable dtrslt = (DataTable)ViewState["dirState"];
if (dtrslt.Rows.Count > 0)
{
if (Convert.ToString(ViewState["sortdr"]) == "Asc")
{
dtrslt.DefaultView.Sort = e.SortExpression + " Desc";
ViewState["sortdr"] = "Desc";
}
else
{
dtrslt.DefaultView.Sort = e.SortExpression + " Asc";
ViewState["sortdr"] = "Asc";
}
ViewState["sortexp"] = e.SortExpression; //resort and store.
ViewState["dirState"] = dtrslt;
GridView1.DataSource = dtrslt;
GridView1.DataBind();
}
}
Now I have a button that will copy the data from the first datatable to a new datatable which only contains the selected rows. I am sure that I am having the computer do more work than it should but I was trying everything.
This code below is copying the data into the new datatable and binding to the repeater control. Works fine if I don't sort the gridview. Please let me know your thoughts or if I need to provide additional information.
protected void CopyToDataTable(object sender, EventArgs e)
{
//Create a new DataTable.
DataTable dtNotary = new DataTable();
DataTable dtrslt = (DataTable)ViewState["dirState"];
dtNotary = dtrslt.Clone();
DataRow dr = dtrslt.Rows[0];
//Loop through the GridView and copy rows.
foreach (GridViewRow gRow in GridView1.Rows)
{
CheckBox ckBox = (CheckBox)gRow.FindControl("notaryselect");
if (ckBox.Checked)
{
dr = dtrslt.Rows[gRow.RowIndex];
dtNotary.ImportRow(dr);
}
}
RepeaterNotary.DataSource = dtNotary
RepeaterNotary.DataBind();
}
Ok, keep in mind that you using the "default" view.
that means the table (and hence row index INTO that table will not match) after you sort.
So, when you use a "data view", it does NOT effect nor change the order of hte base table.
So, this:
DataTable rstData = new DataTable();
rstData = General.MyRst("SELECT ID, HotelName FROM tblHotelsA");
for (int i = 0; i < rstData.Rows.Count; i++)
{
Debug.Print($"{rstData.Rows[i]["ID"].ToString()} H= {rstData.Rows[i]["HotelName"]}");
}
// now sort table by id REVERSE order!
rstData.DefaultView.Sort = "ID DESC";
for (int i = 0; i < rstData.Rows.Count; i++)
{
Debug.Print($"{rstData.Rows[i]["ID"].ToString()} H= {rstData.Rows[i]["HotelName"]}");
}
Debug.Print("---- sorted output");
foreach(DataRowView OneRow in rstData.DefaultView)
{
Debug.Print($"{OneRow["ID"].ToString()} H= {OneRow["HotelName"]}");
}
Output:
1 H = My Cool
2 H = Ramada Lodge
3 H = Sandman Inn
4 H = Super 8
5 H = Inns of Banff
6 H = Swiss Village
7 H = Mary's Motel
16 H = Batman's Cave
1 H = My Cool
2 H = Ramada Lodge
3 H = Sandman Inn
4 H = Super 8
5 H = Inns of Banff
6 H = Swiss Village
7 H = Mary's Motel
16 H = Batman's Cave
---- sorted output
16 H = Batman's Cave
7 H = Mary's Motel
6 H = Swiss Village
5 H = Inns of Banff
4 H = Super 8
3 H = Sandman Inn
2 H = Ramada Lodge
1 H = My Cool
NOTE VERY close - after I sorted the "data view", the table order DOES not change when I reference the rows!!!!
Only the 3rd run shows the data sorted. And you could do say this:
Debug.Print("---- sorted output example 2");
DataTable dt2 = rstData.DefaultView.ToTable();
for (int i = 0; i < dt2.Rows.Count; i++)
{
Debug.Print($"{dt2.Rows[i]["ID"].ToString()} H= {dt2.Rows[i]["HotelName"]}");
}
So, in above, I used the "totable()" to get a real sorted view!
Now, lets check the results of that table in the grid view.
this will show this even better:
DataTable rstData = new DataTable();
rstData = General.MyRst("SELECT ID, HotelName FROM tblHotelsA");
// now sort table by id REVERSE order!
rstData.DefaultView.Sort = "ID DESC";
GridView1.DataSource = rstData;
GridView1.DataBind();
foreach (GridViewRow gRow in GridView1.Rows)
{
Debug.Print($"Grid row {gRow.RowIndex} First GV ID = {gRow.Cells[0].Text} First Table row ID = {rstData.Rows[gRow.RowIndex]["ID"]}");
}
Output:
Grid row 0 First GV ID = 16 First Table row ID = 1
Grid row 1 First GV ID = 7 First Table row ID = 2
Grid row 2 First GV ID = 6 First Table row ID = 3
Grid row 3 First GV ID = 5 First Table row ID = 4
Grid row 4 First GV ID = 4 First Table row ID = 5
Grid row 5 First GV ID = 3 First Table row ID = 6
Grid row 6 First GV ID = 2 First Table row ID = 7
Grid row 7 First GV ID = 1 First Table row ID = 16
So, once again, you can see the "default" view is used by the GV, but the base table is still not sorted.
I tend to NOT use the built in "default" data view, since you can wind up with the above confusing. thus, a lot of my code feeds the "data view" to the table, and not the "default view". I do this "only" to reduce confusing.
eg this code is common:
Dim rstGridData As DataTable
rstGridData = MyrstP(cmdSQL)
Dim dView As DataView = rstGridData.DefaultView
dView.RowFilter = strWhere
dView.Sort = "QuoteDate DESC, ID DESC"
Me.ListView1.DataSource = rstBlank
Note HOW I send the data view to the gridview/lv in above.
Ok, I (probably spent too much time on above - my sorry!!).
So, next up:
I would actually re-pull the data based on the PK settings. both GV, and LV have what is called "data keys", and it is a great collection of the PK row "id", and even better is NEVER exposed to the client side browser (good for security - people can't mess with your pk's in the markup!!!).
And also, keep in mind for most cases, re-pulling the data will cost LESS then persisting the data table in viewstate!!!
So, I would say suggest using this:
string MyIdList = "";
foreach (GridViewRow gRow in GridView1.Rows)
{
CheckBox ckBox = (CheckBox)gRow.FindControl("chkActive");
if (ckBox.Checked)
{
if (MyIdList != "")
MyIdList += ",";
MyIdList += GridView1.DataKeys[gRow.RowIndex]["ID"].ToString();
}
}
DataView MyView = rstData.DefaultView;
MyView.RowFilter = $"ID IN({MyIdList})";
Repeater1.DataSource = MyView;
Repeater1.DataBind();
In other words, operate by PK database ID (assuming you have one).
So, in the gv define, you need to set the datakeys "ID" (column name) of the PK value.
eg:
<asp:GridView ID="GridView1" runat="server" CssClass="table"
DataKeyNames="ID" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
etc.
So, datakeys is nice, since then based on GV row, you can always get/have use of the database PK row id, we don't care about order, and even better is the PK row idea does not have to be exposed nor included in the markup.
Currently I have
public void bindgrid()
{
SqlConnection conn = new SqlConnection("Data Source = 'PAULO'; Initial Catalog=ShoppingCartDB;Integrated Security =True");
SqlCommand cmd = new SqlCommand("select p.[name], cd.CustomerName, cd.CustomerEmailID,cd.CustomerPhoneNo,cd.CustomerAddress,cd.TotalPrice,cd.OrderDateTime, cd.PaymentMethod FROM CustomerDetails cd Inner Join CustomerProducts cp ON cp.CustomerID = cd.Id Inner Join Products p ON cp.ProductID = p.ProductID", conn);
SqlDataAdapter da = new SqlDataAdapter("", conn);
da.SelectCommand = new SqlCommand("select p.[name], cd.CustomerName, cd.CustomerEmailID,cd.CustomerPhoneNo,cd.CustomerAddress,cd.TotalPrice,cd.OrderDateTime, cd.PaymentMethod FROM CustomerDetails cd Inner Join CustomerProducts cp ON cp.CustomerID = cd.Id Inner Join Products p ON cp.ProductID = p.ProductID", conn);
DataSet ds = new DataSet();
da.Fill(ds, "data");
GridView1.DataSource = ds.Tables[0].DefaultView;
GridView1.DataBind();
}
and the result:
What I want to happen is that since it is in the same ID (10), would it be possible if I can have multiple values inside my Name column? like lpg, oxygen, etc?
Update: so far I got
this
I just want to store multiple values in my name column to avoid redundancy. please help
Separate your transactions from the items into two separate tables. Use the transaction ID as a foreign key in the items-purchased table. That is:
Remove the column name from your existing table
Create a new table with name and Id
Insert just one row into your existing table with a unique Id
Insert multiple rows into the new table with the same Id and the various names
So your second table would contain rows:
Id name
...
10 Carbon Dioxide
10 Industrial Oxygen
11 (a different purchase)
11 (a different purchase)
...
I am working on an application in asp.net window application whose data stored in excel sheet.
I have a sheet in excel:
Sheet2(STATE,Point)
on the basis of points the each state gets medals which has following criteria:-
Gold : 7 points
Silver : 5 Points
Bronze : 4 Points
I want total medal of each STATE on the basis of their medals type means the STATE having most gold medal should be top.If 2 STATE have same number of Gold then the STATE having more silver medals should be on higher position.And if 2 STATE have same number of silver medals then the STATE having more Bronze medals should be on higher position. I have done following query:-
OdbcConnection con = new OdbcConnection(ConfigurationManager.ConnectionStrings["SportTech"].ConnectionString);
//string query = "select STATE,sum(Point) as MEDAL from [Sheet2$] Group by STATE order by sum(Point) desc";
//string query = "SELECT STATE,SUM(Point) AS MEDAL,(CASE Point == 7: 1 END) AS GoldCount FROM [Sheet2$] GROUP BY STATE ORDER BY SUM(Point) DESC";
string query = "select STATE,sum(Point) as MEDAL, sum(IIF(point = 7,1,0)) as Gold, sum(IIF(point = 5,1,0)) as Silver, sum(IIF(point = 4,1,0)) as Bronce from [Sheet2$] group by STATE order by sum(IIF(point = 7,1,0)) desc";
OdbcCommand cmd = new OdbcCommand(query, con);
OdbcDataAdapter da = new OdbcDataAdapter(cmd);
con.Open();
DataTable dt = new DataTable();
da.Fill(dt);
con.Close();
but the query is not working if 2 STATE having similar Gold or Silver medals.kindly help me..Thanx
Assuming your calculations for the medals works, you should be able to simply add the extra arguments to the ORDER BY clause as so:
string query = "select STATE,sum(Point) as MEDAL, sum(IIF(point = 7,1,0)) as Gold, sum(IIF(point = 5,1,0)) as Silver, sum(IIF(point = 4,1,0)) as Bronce from [Sheet2$] group by STATE order by sum(IIF(point = 7,1,0)) desc, sum(IIF(point = 5,1,0)) desc, sum(IIF(point = 4,1,0)) desc";
I am working on a window application in ASP.NET. To store the data I am using an Excel sheet. The Excel sheet has following fields:
STATE
Point
For getting I have following criteria:
Gold - 7 Point
Silver- 5 Points
Bronze- 4 Points
I want to count total number gold, silver and bronze medal obtained by each State. For this I used following query:
OdbcConnection con = new OdbcConnection(ConfigurationManager.ConnectionStrings["SportTech"].ConnectionString);
//string query = "select STATE,sum(Point) as MEDAL from [Sheet2$] Group by STATE order by sum(Point) desc";
string query = "SELECT STATE,SUM(Point) AS MEDAL,SUM(CASE WHEN Point = 7 THEN 1 ELSE 0 END) AS GoldCount,SUM(CASE WHEN Point = 5 THEN 1 ELSE 0 END) AS SilverCount,SUM(CASE WHEN Point = 4 THEN 1 ELSE 0 END) AS BronzeCount FROM [Sheet2$] GROUP BY STATE ORDER BY SUM(Point) DESC";
OdbcCommand cmd = new OdbcCommand(query, con);
OdbcDataAdapter da = new OdbcDataAdapter(cmd);
con.Open();
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
con.Close();
But it is showing the error:
ERROR [42000Օ] [Microsoft][ODBC Excel Driver] Syntax error (missing
operator) in query expression 'SUM(CASE WHEN Point = 7 THEN 1 ELSE 0
END)'.
How can I resolve this error?
Thanks!
If I understood correctly you could try this. I'm using OleDB instead of Odbc
string constring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\\statetest.xls;Extended Properties=\"Excel 8.0;HDR=YES\"";
OleDbConnection con = new OleDbConnection(constring);
string query = "select STATE,sum(IIF(point = 7,1,sum(IIF(point = 5,1,sum(IIF(point = 4,1,0)))))) as PointsPerState,sum(IIF(point = 7,1,0)) as Gold, sum(IIF(point = 5,1,0)) as Silver, sum(IIF(point = 4,1,0)) as Bronce from [Sheet2$] group by STATE";
OleDbCommand cmd = new OleDbCommand(query, con);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
con.Open();
DataTable dt = new DataTable();
da.Fill(dt);
SELECT *
FROM [productDetail]
WHERE
Price BETWEEN 0 AND 2000
OR Price BETWEEN 2000 AND 12000
AND CategoryID = 2
AND caravanOffline = 0
ORDER BY
price
The query doesn't produce the desired output, it also shows the products whose categoryID is 3,1 etc.
Can any one spot the problem in the query.
Updated code:
static public DataTable GetSelectedFilterMotorhomes(ArrayList caravans)
{
string sqldefault = "Select * from productDetail Where";
string sqlBuilder = "";
int starter = 0;
int count = caravans.Count;
string sqlOperator = "OR";
if (caravans.Count > 0)
{
while (count > starter) //build the query depending on the number of caravans.selected.count
{
sqlBuilder += "((Price between " + caravans[count - 1] + "))" + sqlOperator;
count--;
}
string addQuery = sqldefault + sqlBuilder;
string removeOR = addQuery.Substring(0, addQuery.Length - 2); //remove OR
string finalQuery = removeOR + "AND (CategoryID = 2) AND (caravanOffline = 0) order by Price"; //Display caravans in ascending order
SqlDataAdapter da = new SqlDataAdapter(finalQuery, ConnectionString);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
else
{
string returnAllCaravans = "Select * from productDetail WHERE CategoryID = 2 AND caravanOffline = 0";
SqlDataAdapter da = new SqlDataAdapter(returnAllCaravans, ConnectionString);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
}
You may need some parenthesis? I'd need to know exactly what you were trying to pull back with your query but likely you need a parenthesis after the OR and then again either after the CategoryID = 2 or after the caravanOffline = 0. See if either of the following queries returns what you're looking for.
Select
*
from [productDetail]
WHERE
Price between 0 AND 2000
OR (Price between 2000 AND 12000 AND CategoryID = 2) AND caravanOffline = 0
order by price
Select
*
from [productDetail]
WHERE
Price between 0 AND 2000
OR (Price between 2000 AND 12000 AND CategoryID = 2 AND caravanOffline = 0)
order by price
What do you really want to do with your WHERE clause?? Without any parenthesis, it's not clear at all what you're trying to select
DO you really mean:
WHERE
(Price BETWEEN 0 AND 2000 OR Price BETWEEN 2000 AND 12000)
AND CategoryID = 2
AND caravanOffline = 0
Price is between 0 and 2000, or between 2000 and 12000 (doesn't really make sense), AND in any case, the CategoryID is 2 ?
Or do you mean:
WHERE
Price BETWEEN 0 AND 2000
OR
(Price BETWEEN 2000 AND 12000 AND CategoryID = 2 AND caravanOffline = 0)
The price is either between 0 and 2000 (with no other restriction) OR the price is between 2000 and 12000, but only if the CategoryID = 2 and CaravanOffline = 0 are true at the same time) ??
Or are you looking for something else than these two options??
I think it might need some brackets...
SELECT * FROM productDetail
WHERE Price BETWEEN 0 AND 2000
OR (Price BETWEEN 2000 AND 12000
AND CategoryId = 2
AND caravanOffline = 0)
ORDER BY price
Assuming that's the logic you want! Your question is rather vague, I'm assuming that you want caravans under 2000 regardless of category and caravanOffline, or caravans between 2000 and 12000 with a categoryid of 2 and caravanOffline of 0.