Make it appear in Not-Submitted list - c#

I want to retrieve back Student names and Student ID that don't exist in the Submission table, but exist in the Students table, and bind it into the GridView. For example Class A has 40 students, but only 38 students submitted the project. I want the 2 students who don't submit to appear in the GridView where the Teacher can view it
SELECT *
FROM Students
LEFT JOIN dbo.Submission ON Students.Student_Id = Submission.Student_Id
AND Students.Subject_Id = Submission.Subject_Id
WHERE Students.Subject_Class='" + Session["Subject_Class"].ToString() + "'
AND Students.Subject_Id = '" + Session["Subject_Id"].ToString() + "'
AND Submission.Proj_Sub = '" + Session["Proj_Sub"].ToString() + "'
And Submission.Student_Id IS NULL
When I use the above-mentioned statement, the GridView appears to be empty.

You probably want something like this.
SELECT *
FROM Students
WHERE Students.Subject_Class='" + Session["Subject_Class"].ToString() + "'
AND Students.Subject_Id = '" + Session["Subject_Id"].ToString() + "'
AND NOT EXISTS (SELECT *
FROM Submissions
WHERE Submissions.Student_Id = Students.Student_Id
AND Submissions.Subject_Id = Students.Subject_Id
AND Submissions.Proj_Sub = '" + Session["Proj_Sub"].ToString() + "')
There are a number of approaches you could take, but this seems like the cleanest. Most importantly, though, you should place emphasis on moving away from your currently-SQL-injection prone approach. Please parameterize your queries.

Related

SQL statement that only fetches the newest department which has been allocated

In my database i have the following rows and columns: https://i.imgur.com/ktUZY9d.jpg
My problem is the same employee has 3 different departments, but he is currently only active in 1. How do I change this SQL statement to only include the latest department he is in, which started in 2018 and ends in 2100, as seen by the ALLOCATION_START and ALLOCATION_END?
Query
string agentIdSubQuery = "SELECT DISTINCT " +
"AGENT_ID " +
"FROM " +
"KS_DRIFT.V_AGENT_ALLOCATION " +
"WHERE " +
"LENGTH(AGENT_INITIALS) < 5";
if(queryParams.SnapshotDate.HasValue)
agentIdSubQuery += " AND " + OracleConversion.ToOracleDate(queryParams.SnapshotDate) + " BETWEEN ALLOCATION_START AND ALLOCATION_END";
Update:
Tried alot of different solutions, but it crashes everytime, when i run through the debugger, further Down in this method this Query is causing me to crash:
string sql = "SELECT " +
"age1.* " +
"FROM " +
"KS_DRIFT.V_AGENT_ALLOCATION age1 " +
"INNER JOIN " +
"(" + agentIdSubQuery + ") age2 ON age1.AGENT_ID = age2.AGENT_ID " +
"ORDER BY " +
"AGENT_INITIALS";
Error Message:
{"Error occured during execution of SQL query: SELECT age1.* FROM KS_DRIFT.V_AGENT_ALLOCATION age1 INNER JOIN (SELECT max(DISTINCT AGENT_ID FROM KS_DRIFT.V_AGENT_ALLOCATION WHERE LENGTH(AGENT_INITIALS) < 5 AND '2018-08-15' BETWEEN ALLOCATION_START AND ALLOCATION_END AND (UPPER(AGENT_INITIALS) = 'JKKA')) age2 ON age1.AGENT_ID = age2.AGENT_ID ORDER BY AGENT_INITIALS."}
Also giving me an inner exception:
{"ORA-00904: \"AGE2\".\"AGENT_ID\": ugyldig identifikator"}
Debugging error screeenshot
Order it by the newest start date (descending) and select Top 1!
string agentIdSubQuery = "AGENT_ID " +
"FROM " +
"KS_DRIFT.V_AGENT_ALLOCATION " +
"WHERE " +
"LENGTH(AGENT_INITIALS) < 5 " +
" AND ROWNUM = 1 " +
" ORDER BY ALLOCATION_START DESC";
EDIT, changed Top 1 to Rownum = 1, for Oracle syntax
The table V_AGENT_ALLOCATION contains various departments per agent along with the dates the agent worked there. You want an agent's last department, which you get with Oracle's KEEP LAST. You haven't given us much information on your table, though. Let's say that the department is referenced by an allocation_id:
select
agent_id,
max(id_allocation) keep (dense_rank last order by allocation_start)
as id_current_allocation
from v_agent_allocation
group by agent_id
order by agent_id;
Your error message shows the final generated SQL:
{"Error occurred during execution of SQL query: SELECT age1.* FROM KS_DRIFT.V_AGENT_ALLOCATION age1 INNER JOIN (SELECT max(DISTINCT AGENT_ID FROM KS_DRIFT.V_AGENT_ALLOCATION WHERE LENGTH(AGENT_INITIALS) < 5 AND '2018-08-15' BETWEEN ALLOCATION_START AND ALLOCATION_END AND (UPPER(AGENT_INITIALS) = 'JKKA')) age2 ON age1.AGENT_ID = age2.AGENT_ID ORDER BY AGENT_INITIALS."}
If you format that so that it's readable, you get:
select age1.*
from ks_drift.v_agent_allocation age1
inner join
( select max(distinct agent_id
from ks_drift.v_agent_allocation
where length(agent_initials) < 5
and '2018-08-15' between allocation_start and allocation_end
and (upper(agent_initials) = 'JKKA') ) age2
on age1.agent_id = age2.agent_id
order by agent_initials
Two syntax issues should jump out:
There is a missing closing bracket after max(distinct agent_id (the distinct is also redundant)
The date literal is missing its date keyword - it should be date '2018-08-15' (or better still, a bind variable).
The brackets around (upper(agent_initials) = 'JKKA') are redundant but perhaps they arise from your generator logic and it's easiest to keep them.
I'm not sure how that relates to your 'newest allocated department' requirement, though. Some sample data (not a screenshot) would help.
If you're looking for the current department, you should compare the allocation dates with the current date.
Your query already has this WHERE clause, so it should work just fine for the example provided. But if you might want to specify that you need only ONE row using the ROWNUM special variable clause (assuming it's Oracle).
SELECT DISTINCT AGENT_ID
FROM KS_DRIFT.V_AGENT_ALLOCATION
WHERE LENGTH(AGENT_INITIALS) < 5
AND ALLOCATION_START < CURRENT_DATE AND CURRENT_DATE < ALLOCATION_END
AND ROWNUM = 1

How to perform UPDATE operation on two tables having two similar fields and one different field?

I have got two tables named "studentBio" and "subjects". Fields of both tables are being given below(with some values): On the form i have got something like this:
AND in checkedlistbox1 i am showing corresponding subjects in the form like A+B+C. Which after retrieving from user would be split on the basis of '+' and be added into subjects table all at once.
Fields of studentBio table are given as follows: WHERE (RollNo, RegYear,program, and faculty combine to make composite primary key):
RollNo RegYear stuName program faculty phoneNuber Address
1 2010 John Intermediate Pre-Engineering 343483834 London
2 2011 Leonard Intermediate Pre-Medical 454545445 NewYork
3 2012 Henry Graduation B.A 565656565 Oslo
Similary fields of subjects table are as follows: WHERE
(RollNo, RegYear,program, and faculty combine to make composite
primary key):
RollNo RegYear program faculty subjectName
1 2010 Intermediate Pre-Engineering A
1 2010 Intermediate Pre-Engineering B
1 2010 Intermediate Pre-Engineering C
2 2011 Intermediate Pre-Medical D
2 2011 Intermediate Pre-Medical E
2 2011 Intermediate Pre-Medical F
and so on. Now lets come to the problem. What i am doing is UPDATING (faculty and program) in both tables and subjectN in subjects table. What i have done so far is that i have updated only studentBio table which is quite easy but i can't figure-out as how could i structure my update query to update subjects table? Can somebody please help me structuring the query?
If I understood well, please try this restructured version of your query:
string update_Personal = "UPDATE studentBio INNER JOIN subjects ON studentBio.RollNo = subjects.RollNo AND studentBio.RegYear = subjects.RegYear AND studentBio.program = subjects.program AND studentBio.faculty = subjects.faculty SET studentBio.program = ProgramU, studentBio.faculty = FacultyU, subjects.subjectName = SubjectNameU WHERE studentBio.RollNo = " + Convert.ToInt32(this.rollNumber7_combo.SelectedItem.ToString()) + " AND studentBio.RegYear = " + Convert.ToInt32(this.comboBox3.SelectedItem.ToString()) + " AND studentBio.program = '" + this.comboBox1.SelectedItem.ToString() + "' AND studentBio.faculty = '" + this.comboBox2.SelectedItem.ToString() + "'";
I've added the following parts to make it update subjects table:
studentBio INNER JOIN subjects ON studentBio.RollNo = subjects.RollNo AND studentBio.RegYear = subjects.RegYear AND studentBio.program = subjects.program AND studentBio.faculty = subjects.faculty - this part joins the subjects table making it's update possible
, subjects.subjectName = SubjectNameU - fragment in the SET block updating subjectName column in subjects table
WHERE studentBio.RollNo = " + Convert.ToInt32(this.rollNumber7_combo.SelectedItem.ToString()) + " AND studentBio.RegYear = " + Convert.ToInt32(this.comboBox3.SelectedItem.ToString()) + " AND studentBio.program = '" + this.comboBox1.SelectedItem.ToString() + "' AND studentBio.faculty = '" + this.comboBox2.SelectedItem.ToString() + "'" - the last part is the WHERE block in which prefix studentBio. was added to each key column to precise to which table the filtering should be applied (because both tables ha the same key column names)
I hope it could help you in some way.

how to write sql statement in c# to join data

Im trying to join data from different tables and displaying them in datagrid, but im getting an error.
I'm trying to get this info from those tables. Btw, the users needs to type in his id.
RESERVATIONS
UPDATE
" + this.UserID + " is an actual ID of user (int)
bookingID : 1 (int)
bookID : 3 (int)
userID : 1 (int)
USERS
Name : Jack (string)
LastName : Jones (string)
BOOKS
NameOfTheBook : Lord of the Rings (string)
END RESULT
1, 3, 1 Jack Jones, Lord of the Rings (in a data grid table)
string Query =
"SELECT bookingID, bookID, userID, Name, LastName, NameOfTheBook " +
"FROM Reservations, Users, Books "+
"WHERE userID = " + thisUserID.Text +
" AND Users.ID = " + thisUserID.Text +
" AND Books.ID = " + thisUserID.Text + "";
ERROR
The value of at least one of the required parameters has not been determined
How do I fix it?
Step through it and take a look at what Query evaluates to. I suspect it might be you're not linking on the correct fields.
Should it read like more this? :
string Query =
"SELECT bookingID, bookID, userID, Name, LastName, NameOfTheBook " +
"FROM Reservations, Users, Books "+
"WHERE userID = " + thisUserID.Text +
" AND Users.ID = Reservations.userID"
" AND Books.ID = Reservations.bookID";
If userID is a text field then you'd have to put triple quotes in instead of single to get the userID wrapped correctly.

how to insert from different inputs

i am trying to insert different values into a table from my database , i retrieve these values from different tables , input from textBox in Windows form etc ..
but the syntax of my query is not correct , i want to know if there is a possiblity to insert these inputs in one query :
String query4 = #"INSERT INTO FACFIN
(Nom_pren_RS,trimestre,exercice,Nb_factures,Prix_total_HT)
values
('" + textBox1.Text + "','" + textBox3.Text + "','" + textBox2.Text + "',
SELECT cast(count(trimestre) AS varchar(6)) AS Nb_factures FROM facture
WHERE
(facture.Nom_pren_RS='" + textBox1.Text + "'),
SELECT cast(SUM (cast(Prix_vente_HT AS BIGINT ))AS varchar(15))
from facture
where (facture.Nom_pren_RS='" + textBox1.Text + "') ) ";
i know that there is a risk of sql injection and i know that i have to use parameters but i just wanted to test the code to see if it does insert , the syntax of the insert is probably wrong
the nb_factures it should be varchar(6) so i casted it
the column Prix_vente_HT in table facture is varchar so i casted it
to BIGINT to execute the SUM and then casted the SUM to varchar
because the Prix_total_HT should be varchar in the table FACFIN
You cannot add a select statement to a values list, instead this select statement keeps your aggrigates but brings the text box values into a single select statement. If you need to pull rows from multiple tables you can also do a UNION on the select section.
String query4 = #"INSERT INTO FACFIN (Nom_pren_RS,trimestre,exercice,Nb_factures,Prix_total_HT)
SELECT '" + textBox1.Text + "','" + textBox3.Text + "','" + textBox2.Text + "', cast(count(trimestre) AS varchar(6)) AS Nb_factures ,
cast(SUM (cast(Prix_vente_HT AS BIGINT ))AS varchar(15)) as Prix_total_HT
FROM facture
WHERE (facture.Nom_pren_RS='" + textBox1.Text + "')";
The result would look something like this to SQL Server
INSERT INTO FACFIN (Nom_pren_RS,trimestre,exercice,Nb_factures,Prix_total_HT)
SELECT
'TEXT_BOX_1_VALUE','TEXT_BOX_3_VALUE','TEXT_BOX_2_VALUE',
cast(count(trimestre) AS varchar(6)) AS Nb_factures, cast(SUM (cast(Prix_vente_HT AS BIGINT ))AS varchar(15)) as Prix_total_HT
FROM facture WHERE (facture.Nom_pren_RS='TEXT_BOX_1_VALUE')

Eager loading child collections with the help of Future and HQL

I am trying to load the child collection of a child of the entity I am selecting. I am trying to mimic this way of doing it, basically creating two future queries and then enumerating one of them. This should lead to two queries to the database:
var idd = session.CreateQuery("from ItemDeliveryDetail idd " +
"join fetch idd.ItemDelivery " +
"left join fetch idd.SupplierInvoice " +
"where idd.Id = 21931828")
.Future<ItemDeliveryDetail>();
var spc = session.CreateQuery("from SpecialCondition spc " +
"where spc.ItemDelivery " +
"in (select idd.ItemDelivery " +
"from ItemDeliveryDetail idd " +
"where idd.Id = 21931828)")
.Future<SpecialCondition>();
var result = idd.ToList();
The last line indeed results in two queries to the database. The queries are exactly what I expect (They are rather lengthy and I don't think they are relevant to the question, but if you would like to see them, I pasted them here).
Problem is, the results of those two queries are not combined, i.e. the following enumeration will still query the database for the SpecialConditions of each ItemDelivery:
foreach (var itemDeliveryDetail in result)
{
foreach (var specialCondition in itemDeliveryDetail.ItemDelivery
.SpecialConditions)
{
// Do something
}
}
How to fix that?
Your second query does not load the ItemDelivery.SpecialConditions collections; only an unused list of SpecialConditions.
I agree with Rippo in that using batch-size is usually cleaner and more performant, even if it results in one or two more roundtrips.
That said, your second query should be:
var spc = session.CreateQuery("from ItemDelivery id " +
"join fetch id.SpecialCondition "
"where id in (select idd.ItemDelivery " +
"from ItemDeliveryDetail idd " +
"where idd.Id = 21931828)"
.Future<ItemDelivery>();
One quick win might be to add batch-size=50 to the bag mapping between ItemDelivery and SpecialConditions.
However I suggest you read this blog "Eagerly loading entity associations efficiently with NHibernate" post from Ayende as it might provide you with the answer you are looking for.
You are facing the classic select n + 1 problem here. I would rather have 1 or maybe 2 more trips to the database rather than a big cartesian product resultset. I am sure this will be the most performant route.
You need to use the same base query twice which I think is your problem.
var idd = session.CreateQuery("from ItemDeliveryDetail idd " +
"join fetch idd.ItemDelivery " +
"left join fetch idd.SupplierInvoice " +
"where idd.Id = 21931828")
.Future<ItemDeliveryDetail>();
var spc = session.CreateQuery("from ItemDeliveryDetail idd " +
"join fetch idd.ItemDelivery id " +
"join fetch id.SpecialCondition spc " +
"where idd.Id = 21931828")
.Future<ItemDeliveryDetail>();
var result = idd.ToList();
Yes I realise this may cause a cartesian product for you but I have had good success using this technique.

Categories

Resources