Hi. I have 2 data tables like this:
I want to get the ID in Table1 if the User in Table2 exists or does not exist
This is the code I test and get the data:
string idGet = "";
string getValue = "Select ID, Port, User from Table1";
DataTable dtgetValue = XLDL.ReadTable(getValue);
if(dtgetValue.Rows.Count > 0)
{
List<ListOtherUser> listOtherUser = new List<ListOtherUser>();
for (int i = 0; i < dtgetValue.Rows.Count; i++)
{
listOtherUser.Add(new ListOtherUser { ID = dtgetValue.Rows[i]["ID"].ToString(), User = dtgetValue.Rows[i]["User"].ToString(), Port = dtgetValue.Rows[i]["Port"].ToString() });
}
foreach (var itemuser in listOtherUser)
{
string checkUser = "Select ID from Table2 where User = N'" + itemuser.User + "'";
DataTable dtcheckUser = XLDL.ReadTable(checkUser);
if (dtcheckUser.Rows.Count > 0)
{
idGet += itemuser.ID + ",";
}
else
{
//Here I want to continue to get the data of row ID=3 from Table1. However I don't know how to solve it?
}
}
}
As the data above I want the output as: idGet = 1 and 3 from Table1
With data from Table1 and Table2:
As the data above I want the output as: idGet = 2 and 3 from Table1
Looking forward to a solution from everyone. Thank you!
The best solution here though would be to do some SQL joins and exclude it coming in, but if you want a solution in code instead, depdending on how large that dataset is/will be, this is a good spot for LINQ.
var result = Table2.Where(p => table1.All(p2 => p2.UserID != p.UserID));
Adapted from this question.
If you opted for SQL, your query would look something more like this and while looking at your logic, you should absolutely not do that how you are trying to. That is so many single db calls for absolutely no reason.
Select Table1.ID
FROM Table1 LEFT OUTER JOIN
Table2 ON Table1.User = Table2.User
WHERE Table2.ID IS NULL;
Related
I'm trying to learn C# and have come across a problem that I hope you guys will know an easy solution.
I want to run two possible LINQ queries but reading from different places and returning a 2 different fields (both id's) based on an IF condition.
In VB6 it would have been something simple like:
Dim strQuery as string
Dim rs as adodb.recordset
If 1 = 1 then
strQuery = "Select messageid as id1, refid as id1 from x where ..."
else
strQuery = "Select commonid as id1, nextid as id2 from x where ..."
endif
set rs = cn.execute(strquery)
debug.print rs!id1 & rs!id2
How can this be done in c#?
I've tried:
IQueryable fD = null;
if (1 == 1)
{
fD = from qa in data.table1
select qa;
}
else
{
fD = from qa in data.table2
select qa;
}
foreach (var a in FD)
{
// Unable to see any data.
}
Thankyou Tetsuya Yamamoto for pointing me in the right direction IQueryable strQuery
foreach (**dynamic** a in strQuery)
{
//a.CentralContractorID
}
dynamic was the word which was missing, it now works perfect.
I'm doing a "load" button to load up all datas from a SQL database, to put them in a listview.
if(lstEnsemble.Items.Count == 0)
{
MySqlConnection connexion = OpenConnection();
MySqlCommand reqRemplissageClient = new MySqlCommand("select * from client order by idClient ASC;", connexion);
MySqlCommand reqRemplissagePanne = new MySqlCommand("select * from Panne order by idClient ASC;", connexion);
MySqlDataReader resultatClient = reqRemplissageClient.ExecuteReader();
MySqlDataReader resultatPanne = reqRemplissageClient.ExecuteReader();
while (resultatClient.Read() && resultatPanne.Read())
{
ListViewItem item = new ListViewItem(resultatClient["nomCli"].ToString());
item.SubItems.Add(resultatClient["prenomCli"].ToString());
if (resultatClient["idClient"] == resultatPanne["idClient"])
{
item.SubItems.Add(resultatPanne["appareil"].ToString());
}
item.SubItems.Add(resultatClient["villeCli"] + " " + resultatClient["cpCli"] + " " + resultatClient["rueCli"]);
item.SubItems.Add(resultatClient["telCli"].ToString());
if (resultatClient["idClient"] == resultatPanne["idClient"])
{
item.SubItems.Add(resultatPanne["description"].ToString());
item.SubItems.Add(resultatPanne["dateEntree"].ToString());
}
item.SubItems.Add(resultatClient["mailCli"].ToString());
lstEnsemble.Items.Add(item);
}
CloseConnection(connexion);
}
This does not work, obviously, but I can't manage to find another way to do this.
I tried to do both of requests separately, but again I'm missing the logic to this.
In your question it's not fully clear what kind of data you are working with. It seems your presuming (or better hoping) that the idClient values match exactly in both tables.
I presume that you actually want to do a JOIN. If this is not true, I will delete this post again.
So you should do only one query using a JOIN:
if(lstEnsemble.Items.Count == 0)
{
string sql = #"SELECT nomCli, prenomCli, appareil, villeCli, rueCli,
cpCli, telCli, description, dateEntree, mailCli
FROM client LEFT JOIN Panne ON (client.idClient = Panne.idClient)";
MySqlConnection connexion = OpenConnection();
MySqlCommand request = new MySqlCommand(sql, connexion);
MySqlDataReader resultat = requestExecuteReader();
while (resultat.Read())
{
ListViewItem item = new ListViewItem(resultat["nomCli"].ToString());
item.SubItems.Add(resultat["prenomCli"].ToString());
item.SubItems.Add(resultat["appareil"].ToString());
item.SubItems.Add(resultat["villeCli"] + " " + resultat["cpCli"] + " " + resultat["rueCli"]);
item.SubItems.Add(resultat["telCli"].ToString());
item.SubItems.Add(resultat["description"].ToString());
item.SubItems.Add(resultat["dateEntree"].ToString());
item.SubItems.Add(resultat["mailCli"].ToString());
lstEnsemble.Items.Add(item);
}
CloseConnection(connexion);
}
But you should be aware that for rows in client with no matching rows in Panne there will be null values in the results. So you need to check for them first using resultat.IsDbNull() on the column index (position in sql query).
Alternativly you may use an INNER JOIN instead of a LEFT JOIN to get only rows that exist in both tables.
You should change a few things, then it becomes pretty easy.
Make a single SQL Query. Just JOIN your tables together and SELECT what you need.
Separate the Database access from filling your listview. Put your result in an array or datatable.
With your data available you can easily bind it or iterate through it to generate ListViewItems.
I have three tables in my Access database
Part (tbl name)
PartNo
UnitPrice
Order(tbl name)
OrderNo
OrderLine (tbl name)
OrderNo
PartNo
Quantity
Basically I want to sum(Quantity by UnitPrice) of all the OrderLines where OrderLine.PartNo = Part.PartNo and OrderLine.OrderNo = Order.OrderNo and place the value in a column I created and added onto the data grid view so it creates a subtotal in the order table on the fly.
DataGridViewTextBoxColumn subtotalCol = new DataGridViewTextBoxColumn();
subtotalCol.Name = "SubtotalColumn";
subtotalCol.HeaderText = "Subtotal";
subtotalCol.ReadOnly = true;
dataGridViewPrevOrders.Columns.Add(subtotalCol);
This is where I am so far but I don't think I'm going about it the right way!
for (int i = 0; i < dataGridViewPrevOrders.RowCount - 1; i++)
{
connection.Open();
string orderNo = dataGridViewPrevOrders.Rows[i].Cells["OrderNo"].Value.ToString();
command.CommandText = "SELECT SUM(OL.Quantity * P.UnitPrice) FROM OrderLine OL INNER JOIN (SELECT * FROM [Part]) P ON OL.[PartNo] = P.[PartNo] WHERE [OrderNo] = #OrderNo";
command.Parameters.Add(new OleDbParameter("#orderNo", orderNo));
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
dataGridViewPrevOrders.Rows[i].Cells["SubtotalColumn"].Value = reader["Sub"].ToString();
}
connection.Close();
}
First: Please add the specific problem! Does it lead to an exception? What is the undesired behaviour? Please help us to help you.
On first sight I can only see that you have to correct your sql command to:
SELECT SUM(P.UnitPrice * OL.Quantity) AS sumOfOrder FROM Part AS P
INNER JOIN OrderLine AS OL ON P.[PartNo] = OL.[PartNo]
WHERE OL.[OrderNo] = #OrderNo;
Hint: Regarding your code, it seems to me that you must have an extra SQL-command somewhere to set the Orders to the dataGridViewPrevOrders. Then you want to execute an extra SQL command for every Order to calculate the sum. It would be better to query the sum of quantity and OrdersNo with one clever SQL SELECT commmand, where you combine these two Queries and set it in only one loop.
I have two tables in my database: Students, and accounts. In my application, I am trying read data from multiple tables using reader.GetDecimal() method and having trouble getting data from the second table.
Is it possible to do this using the GetDecimal method? Or do I need to add to one of the queries to get what I need from the Accounts table?
Database Tables:
Accounts
Student
Code:
//Query Student table for bAlertSetup
SqlCeCommand AlertQuery = new SqlCeCommand("SELECT * from Students AND Accounts", conn);
reader = AlertQuery.ExecuteReader();
while (reader.Read())
{
bSinglePersonAlertSetup = reader.GetBoolean(5);
if (bSinglePersonAlertSetup == true)
{
int AccountID = reader.GetInt32(7);
decimal Threshold = reader.GetDecimal(6);
//decimal Total = get decimal from the accounts table where accountID (in the accounts table) = AlertAccountID
//See if Students account is below the defined threshold
if (Total < Threshold)
{
StudentEmailAddress = reader.GetString(3);
if (StudentEmailAddress != null)
{
Console.WriteLine(StudentEmailAddress);
mail.To.Add(StudentEmailAddress);
//Update bAlertSetup
SqlCeCommand UpdateBool = new SqlCeCommand("UPDATE Students set bSendAlert = 0 WHERE UserId = #ID");
UpdateBool.Parameters.AddWithValue("#ID", reader.GetInt32(0));
UpdateBool.Connection = conn;
UpdateBool.ExecuteNonQuery();
}
}
}
EDIT:
Here is the new query I am using that I believe joins the two tables correctly with the columns needed. Now, how do I get the index of each column to use in the GetDecimal() Method?
SqlCeCommand AlertQuery = new SqlCeCommand("SELECT st.bAlertSetup, st.AccountThreshold, st.AlertAccountID, acc.AccountID, acc.AccountTotal FROM Students st INNER JOIN Accounts acc ON st.AlertAccountID = acc.AccountID", conn);
SqlCeCommand AlertQuery = new SqlCeCommand("SELECT S.*,A.AccountTotal from Students S Inner Join Accounts A ON S.AlertAccountID = A.AccountID");
Make sure to execute the query in sql and know the index of each column to provide the correct index, or replace S.* by S.[FieldName] for each field comma seperated and that the order of your columns will be always preserved in the query.
You should properly join the two tables in your query, and only select the individual columns you need. So your query might be something like below...
SELECT st.UserID, st.FirstName, st.LastName, acc.AccountName, acc.AccountTotal
FROM Student st
JOIN Accounts acc
ON st.AlertAccountID = acc.AccountID
You could get the AccountTotal then by name, like this...
decimal total = reader.GetDecimal("AccountTotal");
http://msdn.microsoft.com/en-us/library/system.data.datatablereader.getdecimal(v=vs.90).aspx
You can use this
decimal total = reader.GetDecimal(2); //index column name
hope will help you
I am trying to develop an application using ADO.NET. I have two tables in two different databases. Each of them have a portion of the complete data. Now I need to write a query such that I am able to fetch the complete record from the two tables. As an example say table 1 has Index_no,emp_ID and contact no. Table 2 has index_no, emp_name, salary and dept. The index_no is same for the same record portion in each table.
Following is the code to fetch all records where salary <20000.
sqlCmd2 = new SqlCommand("SELECT * FROM table1 WHERE Index_No =#Index_No",
TestCon);
int i = 0;
while (reader.Read()) {
ListBox1.Items.Add(reader.GetInt32(0) + " - " +
reader.GetString(1) + " - " + reader.GetString(2));
// Name.Text += reader["Name"] + "<br />"; ;
// Depart.Text += reader["Depart"] + "<br />"; ;
array1[i] = reader.GetInt32(0);
i++;
}
sqlCmd2.Parameters.Add("#Index_No", System.Data.SqlDbType.Decimal);
i = 0;
do {
sqlCmd2.Parameters["#Index_No"].Value = array1[i];
reader1 = sqlCmd2.ExecuteReader();
reader1.Read();
ListBox2.Items.Add(reader1.GetString(1));
i++;
} while (i < array1.Length);
The problem with this is that I am getting only one record info from table2 while for table 1 I get all the desired record info. The do-while loop seems to terminate after one iteration only.
It depends, what two different databases means. If the two databases run on the same SQL-Server, it is easy to access the table of the other database
SELECT * FROM OtherDb.dbo.TableOnOtherDb
If not, I would suggest you to create a database link between the two databases (see SO question How do I create and query linked database servers in SQL Server?). Then you can access the other table as above.
In both cases you can use a JOIN query to join the two tables. Then you will need only one data reader
SELECT
A.Index_no, A.emp_ID, A.contact_no,
B.emp_name, B.salary, B.dept
FROM
table1 A
INNER JOIN table2 B
ON A.Index_no = B.Index_no
WHERE
B.salary < 20000
ORDER BY
B.emp_name
UPDATE
If the number of involved records is small, then querying the second table only once by using a IN clause would be far more efficient, if you cannot link the two servers for some reason.
SELECT *
FROM table1
WHERE Index_no IN (4,12,17,30,112,167)
You would create this SQL statement like this
string[] stringArray = array1
.Select(i => i.ToString())
.ToArray();
string list = String.Join(",", stringArray);
string sql = "SELECT * FROM table1 WHERE Index_No IN (" + list + ")";
The idiomatic way of doing the second loop would be (not do while)
for (int i = 0; i < array1.Length; i++) {
...
}
Why don't you write a stored procedure which joins both the ables and gives back the results? You can connect to the second db using linked server or you can refer the second table using the dbname.tablename format.