How to compare 2 database tables using Java - java

I have a scenario here I need to compare 2 database tables using java
First Database table has
id Name Salary
1 ABC 1000
2 XYZ 2000
3 LMN 3000
Second Database Table has
id Name Salary
4 PQR 5000
2 XYZ 2000
1 ABC 4000
3 LMN 2500
I had used list to compare but is there any other way to compare 1st table with the 2nd table using selenium java.
I want the output to be
Second table has 4 rows while 1 table has 3 rows (or vice versa)
1st table LMN salary is 3000 and second table LMN salary is 2500

I would do the requested comparison in SQL directly. This will be faster. There are a couple of ways to do this depending on the results you need.
Since you are using Microsoft SQL you can retrieve the number of rows in the requested format by doing something like this:
SELECT 'The FirstTable has ' + cast((SELECT count(*) from FirstTable) as varchar(50)) + ' records, while the SecondTable has ' + cast((SELECT count(*) from SecondTable) as varchar(50)) + ' records';
For getting the differences between the tables you can do something like this:
SELECT * FROM FirstTable
UNION
SELECT * FROM SecondTable
EXCEPT
SELECT * FROM FirstTable
INTERSECT
SELECT * FROM SecondTable;
Then you can take ResultSet and compare the entries like this:
while (resultSet.next())
{
int id= rs.getInt("id");
String name= rs.getString("name");
int firstTableSalary = rs.getInt("salary");
rs.next();
int secondTableSalary = rs.getInt("salary");
console.log(String.format("The first table salary is %d, while the second table salary is %d, name=%s, id=%d", firstTableSalary, secondTableSalary, name, id);
}
I prepared here a fiddle for checking the SQLs.

Getting the salary differences is easier with SQL
String query = "select t1.name,t1.salary t1_salary, t2.salary t2_salary" +
" from table1 t1, table2 t2 "+
" where t1.id=t2.id and t1.name=t2.name and t1.salary!=t2.salary";
//this will give you a result set of all the names and salaries from the two tables
//where the salaries differ.
Connection conn = ...
try (Statement stmt = conn.createStatement()){
ResultSet rs = stmt.executeQuery(query);
while (rs.next()){
String name = rs.getString(1);
Integer t1Salary = rs.getInt(2);
Integer t2Salary = rs.getInt(3);
//do something with these values
}
rs.close();
Similarly, capture the table lengths with queries
int t1Length = 0;
int t2Length = 0;
rs = stmt.executeQuery("select count(*) from table1");
while (rs.next()){
t1Length = rs.getInt(1);
}
rs.close();
rs = stmt.executeQuery("select count(*) from table2");
while (rs.next()){
t2Length = rs.getInt(1);
}
rs.close();
//do something with the lengths
}
conn.close();

Related

SQL ResultSet is empty despite having a row returned in tests

I am building a simple program for a library database system in Java where patrons can borrow and return books. The database has 4 tables: Book, Author, Patrons, and AuthorIds. I'm using the SQL statement below to retrieve 1 row of data that includes everything plus a column that counts how many books the patron has already borrowed. The problem is that the program never goes into the while(res.next()) loop and I think it's because the result set is empty. The test print doesn't get printed and membID doesn't get changed to the MemberID of the patron.
But when I try that same SQL statement on db browser on the same database it returns 1 row as expected with the BooksBorrowed column. All of my other ResultSet while loops have worked and returned rows with other SQL statements, it's just this one that doesn't and I don't know why.
public void borrowBooks(String fName, String lName, Scanner input) throws SQLException {
//first find out how many books the user has already borrowed
int booksBorrowed = 0;
int membID = 1; //this will be used for later
sql = "select *, Count(MemberID) AS BooksBorrowed\r\n" +
"FROM Book\r\n" +
" JOIN AuthorIds USING (BookID)\r\n" +
" JOIN Author USING (AuthorID)\r\n" +
" JOIN Patron USING (MemberID)\r\n" +
"WHERE PatronFirstName LIKE ? AND PatronLastName LIKE ?\r\n" +
"GROUP BY MemberID\r\n" +
"ORDER BY BookID ASC";
PreparedStatement stmt = connection.prepareStatement( sql );
stmt.setString(1, fName);
stmt.setString(2, lName);
ResultSet res = stmt.executeQuery();
while(res.next()) {
booksBorrowed = res.getInt("BooksBorrowed");
System.out.println(res.getInt("MemberID"));
System.out.println("Test");
membID = res.getInt("MemberID");
}
if(booksBorrowed >= 2) {
System.out.println("You have already borrowed the maximum amount of 2 books. Return books to borrow more");
}
I figured it out and it was that I should have gotten the memberID in a separate query because I was trying to change it to the corresponding patron in the same query as I was trying to get the number of books borrowed. The problem was that if the patron didn't have any books borrowed, then the result set would be empty and the memberID wouldn't change from what it was temporarily initialized as. This memberID was later inserted into the table for when a book was borrowed so it would be the temporary stand in each time and not the actual memberID of the patron, so the patron would have no books under their name as borrowed.

sql for update "ERROR: column "used" of relation "account" does not exist" even though it does

I have used this method without using the join in the query and it was working as expected. But I added a inner join and now it can't update the "used" column
public HashMap<String, Comparable> getPhoneNumberAndMarkAsUsed() {
String[] colNames = { "phone_number.id", "phone_number.phone_number",
"phone_number.account_id", "phone_number.used AS used",
"(now() AT TIME ZONE account.timezone)::time AS local_time" };
String query = "select " + Stream.of(colNames).collect(Collectors.joining(", "))
+ " from account INNER JOIN phone_number ON account.id = phone_number.account_id where phone_number.used = false order by id DESC limit 1 for update";
HashMap<String, Comparable> account = new HashMap<String, Comparable>();
try (Connection conn = DriverManager.getConnection(url, props); // Make sure conn.setAutoCommit(false);
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(query)) {
conn.setAutoCommit(false);
ResultSetMetaData rsmd = rs.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while (rs.next()) {
for (int i = 1; i <= columnsNumber; i++) {
if (i > 1)
System.out.print(", ");
String columnValue = rs.getString(i);
System.out.print(columnValue + " " + rsmd.getColumnName(i));
}
// Get the current values, if you need them.
account.put("phone_number", rs.getString("phone_number"));
account.put("account_id", rs.getLong("account_id"));
rs.updateBoolean("used", true);
rs.updateRow();
}
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
return account;
}
the loop prints the following
7223 id, 10001234567 phone_number, 1093629 account_id, f used, 23:32:42.502472 local_time
accourding to the output above, then I am use that column "used" is part of the ResultSet. But I get the following Exception
org.postgresql.util.PSQLException: ERROR: column "used" of relation "account" does not exist
This is the query when printed
select phone_number.id, phone_number.phone_number, phone_number.account_id, phone_number.used AS used, (now() AT TIME ZONE account.timezone)::time AS local_time from account INNER JOIN phone_number ON account.id = phone_number.account_id where phone_number.used = false order by id DESC limit 1 for update
used belongs to the phone_number table not the account table. How can this be resolved?
here is the problem in your code:
rs.updateBoolean("used", true);
this statement will try to update the data of table through resultset but to do that you cannot user join and also there is one problem.
As you are updating via resultset it will try to update account table and if we find used column is account table then error occurs.
so your code is trying to find column "used" in account table but it is not there.
try this one:
String query = "select " + Stream.of(colNames).collect(Collectors.joining(", "))
+ " from phone_number INNER JOIN account phone_number ON account.id = phone_number.account_id where phone_number.used = false order by id DESC limit 1 for update";

Duplicate entry whice using distinct keyword in query

I am using java to execute some SQL Queries. Some of them are Getting data from one database(A) and storing in a table in another database(B).After process is done i am deleting all data from table in database(B). I am repeating this process every 5 mins.
Code:
String sql = "delete from newtable";
stmt5 = conn.prepareStatement(sql);
stmt5.executeUpdate(sql);
String sql_1 = "select distinct tbl_alm_log_2000000000.Csn, tbl_alm_log_2000000000.IsCleared, tbl_alm_log_2000000000.Id,tbl_alm_log_2000000000.NEType, tbl_alm_log_2000000000.OccurTime, tbl_alm_log_2000000000.hostIP, tbl_alm_log_2000000000.ExtendInfo From fmdb.dbo.tbl_alm_log_2000000000 Where IsCleared = 0";
ResultSet rs = stmt_1.executeQuery(sql_1);
String sql_2 = "insert into newtable (CSN, IsCleared, Id, NEType, OccurTime, hostIP) values(?,?,?,?,?,?)";
conn.setAutoCommit(false);
PreparedStatement ps = conn.prepareStatement(sql_2);
final int batchSize = 1000;
int count = 0;
while (rs.next()){
ps.setString(1, rs.getString(1)); //csn
ps.setString(2, rs.getString(2)); //iscleared
ps.setString(3, rs.getString(3));//id
ps.setString(4, rs.getString(4));//netype
ps.setString(5, rs.getString(5));//occurtime
ps.setString(6, rs.getString(6));//hostip
ps.addBatch();
if(++count % batchSize == 0) {
ps.executeBatch();
}
}
ps.executeBatch(); // insert remaining records
conn.commit();
ps.close();
It runs perfectly for 10 -20 runs and then gives "duplicate entry error for "value" in Csn as it is Primary key".
I added Distinct keyword in query and it is still giving this error after 10-20 runs.
Note: I m deleting data from newtable befor start of process so it is always adding in a empty table.
Suggest where i am going wrong.
Looks like you have misunderstanding about how does distinct work. In query with several selected columns it will search for distinct tuples of values, not for distinct Csn column only.
There are different ways how to select distinct values by one column only. It generally depends on particular DBMS you use and logic you want to apply for multiply tuples found for same Csn column values. Consider for instance this question: DISTINCT for only one Column
One of general ideas: select distinct single values for Csn column only, then iterate through this list and select first tuple of values with this Csn value (I don't know is it suitable for you select first tuple or not).
when you insert the data , you can add if not exists not make sure your data is unique ( i considered CSN only column in PK)
if not exists(select 1 from tbl_alm_log_2000000000 where CSN=? )
insert into newtable (CSN, IsCleared, Id, NEType, OccurTime, hostIP) values(?,?,?,?,?,?)

JDBC show rows count

I want to print my rows count at the end, But it shows 1
public void showRecords() {
try {
Statement st1 = con.createStatement();
ResultSet result1 = st1.executeQuery("select * from mytable");
while (result1.next()) {
System.out.println(result1.getString(1) + " " + result1.getString(2));
}
ResultSet rs1 = st1.executeQuery("select count(*) from mytable");
int rows = rs1.last() ? rs1.getRow() : 0;
System.out.println("Number of rows is: "+ rows); //print 1
} catch (SQLException sqle) {
System.out.println("Can not excute sql statement");
sqle.printStackTrace();
}
}
Output:
...
Number of rows is: 1
Output: ... Number of rows is: 1
That's absolutely correct because the ouput of a count query like
select count(*) from mytable
would only contain a single row containing the total number of rows. For you to now retrieve that count you should make use of the Resultset's getter methods as usual.
int rows = rs1.getInt(1);
To retrieve the count the way you wanted to; use the same approach with your first query
ResultSet result1 = st1.executeQuery("select * from mytable");
int rows = result1.last() ? result1.getRow() : 0;
System.out.println("Number of rows is: "+ rows); // should print the count
The count(*) does not have a column name (or only a "generated" one that you might not know). Therefor you need to get the value by column index.
Additionally you need to call next() on the ResultSet in order to be able to obtain the value:
ResultSet rs1 = st1.executeQuery("select count(*) from mytable");
int rows = 0;
if (rs1.next() {
rows = rs1.getInt(1);
}
System.out.println("Number of rows is: "+ rows); //print 1
Selecting the count from a RecoredSet always returns a value of 1, i.e. the record containing the result of the query. You want
ResultSet rs1 = st1.executeQuery("select count(*) from mytable");
if (rs1.next()) {
int rows = rs1.getInt("COUNT")
}
You must read the value from the rowcount query, as it is a normal query. Like
rows = rs1.getInt(1);
I've written a blog post about retrieving query metadata without extra roundtrip, which is something people typically do to paginate their data. I really recommend you don't re-run your queries all the time just to count stuff. A simple approach would be to use window functions, which are now supported in a lot of SQL dialects:
SELECT *, count(*) OVER () FROM mytable
Of course, since you're using low level JDBC API to iterate your ResultSet, why not just count things in the client at that point? E.g.
try (ResultSet rs = s.executeQuery("select * from mytable")) {
int i = 0;
while (rs.next()) {
System.out.println(rs.getString(1) + " " + rs.getString(2));
i++;
}
System.out.println("Number of rows is: " + i);
}

How to get COUNT from ResultSet object?

I am passing the following query to a ResultSet object:
String query = "SELECT COUNT( DISTINCT KEY ), SOURCE FROM MY_TBL\n" +
"GROUP BY SOURCE\n" +
"ORDER BY SOURCE";
I want to capture the counts I am getting for each SOURCE and sum them into a total. How can I capture these counts via ResultSet since COUNT isn't a column name in the ResultSet and I don't think I can return it's value via rs.getInt("COUNT")?
getInt is overloaded, use index (an int) instead of a column name:
rs.getInt(1); // the first column is 1
Try having alias
String query = "SELECT COUNT( DISTINCT KEY ) AS COUNT, SOURCE FROM MY_TBL\n" +
"GROUP BY SOURCE\n" +
"ORDER BY SOURCE";
I Think it is better to use
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * from Customer");
ResultSetMetaData rsmd = rs.getMetaData();
int numCols = rsmd.getColumnCount();
I think "getColumnCount" retinto number of column in a table instead of number of rows...

Categories

Resources