I'm beginning to learn about connecting to databases via Java programs. I have a table called City, which contains just two columns: CityName and Population. I want to find the highest population, and then give that population along with the name of the corresponding city.
I know how to get just the highest population (see the following, which I know is probably not ideal but at least is working for me):
double max = 0.0;
String sqlStatement = "SELECT MAX(Population) FROM City";
ResultSet result = stmt.executeQuery(sqlStatement);
if (result.next())
{
highest = result.getDouble(1);
}
System.out.printf("Highest population: %,.0f", highest);
I am pretty sure that to get the highest population PLUS the name of the corresponding city, my Sql statement should eb changed to :
"SELECT CityName, MAX(Population) FROM City GROUP BY CityName";
But I can't get it to work beyond that. I thought I could add something like
String highestCity = result.getString(2)
and then add highestCity to the System.out.printf output line, but that isn't working.
Can anyone help?
Thanks!
How about this ?
String sqlStatement = "SELECT CityName, Population FROM City WHERE Population IN (SELECT MAX(Population) FROM City)";
You want to sort your results by population descending, and limit your query to only return one result. Something like:
SELECT * FROM city ORDER BY population DESC LIMIT 1;
Related
I tried to do a pagination in Java using PrintWriter. I used this as model: https://www.javatpoint.com/pagination-in-servlet.
As you can see in the example code is done in order to work with 3 pages and 5 elements each page.
out.print("<a href='ViewServlet?page=1'>1</a> ");
out.print("<a href='ViewServlet?page=2'>2</a> ");
out.print("<a href='ViewServlet?page=3'>3</a> ");
int total=5;
I don't think it makes any sense to copy all my code since reading from database works.. I just want to have 1 element on each page and have as many pages as elements was found.
So I use
String query = "select * from tabL where name like CONCAT( '%',?,'%') limit "
+ (start-1)+","+total;
with 1 for start and 1 for total..
ResulSet will have size 1 but if I use this
out.print("<a href='ViewServlet?page=1'>1</a> ");
out.print("<a href='ViewServlet?page=2'>2</a> ");
out.print("<a href='ViewServlet?page=3'>3</a> ");
It prints other elements as well.
So please help how could be done to have as many pages as elements are found and 1 element each page.
Do I need to have a select without limit and use the size of resulset obtained with that, is there a better solution ?
PS: someone please explain me how if I put limit with 1,1 ResulSet has size 1 but it can print 3 elements at least.
I would need to know at least the exact number of elements which were retrieved even with limit 1.
Thank you.
To find the total count you can use a count-query:
String countQuery = "select count(*) from tabL where name like CONCAT( '%',?,'%')";
When you execute this query with the same parameter as the query for the data you will get a ResultSet with one row and one column.
You can retrieve it with
Connection con = ...; // you probably already have a Connection
PreparedStatement ps = con.prepareStatement(countQuery);
ps.setString(1, name); // the name pattern that you're searching for
ResultSet rs = ps.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
I am required to fetch the where clause after an update statement e.g.
UPDATE user_accounts SET bio='This is my bio' WHERE user_id = 1 OR name = 'Alex';
At the moment, I am able to get everything after the where clause with the following code:
String query = "UPDATE user_accounts SET bio='This is my bio' WHERE user_id = 1 OR name = 'Alex'";
int index = query.toUpperCase().indexOf("WHERE");
if (index != -1) {
System.out.println(query.substring(index));
}
But then I discovered that this was significantly flawed, since these sample queries would fail:
UPDATE user_accounts SET bio='This is where my bio is' WHERE user_id = 1 OR name = 'Alex';
UPDATE user_accounts SET whereColumn='' WHERE user_id = 1 OR name = 'Alex'
UPDATE user_whereabouts SET columnName='' WHERE user_id = 1 OR name = 'Alex'
Essentially, this fails if table name or any column name or column value under SET contains the word 'where' (case insensitive).
My thinking has currently been along the lines of a regex that does the following:
Checks if the word where is in between ' ' or " " (e.g. bio = "This is where my bio is") and skips it to move to the one which isn't inside the quotes. This will help eliminate the where words found in the SET values. Of course the Java quotes surrounding a string do not apply since they aren't part of the string itself.
Checks that the word where is sandwiched between spaces (e.g. ... WHERE ...). This will help eliminate the where words found in either table name or column name (SQL syntax itself can't allow table name or column name to solely be a reserved word).
Finally, returns the index of the wanted WHERE in order to get the substring (The objective of the question).
I am not very conversant with regexes and thus, I am in need of assistance. Please note that any other ways of achieving the objective will be highly appreciated as well.
You need some kind of SQL parser because regexes will fail short in many cases (for instance what if the where clause has a sub-select?)
I've never tried it but JSQLParser seems like a good solution
Using JSqlParser this would look like:
List<String> sqls = Arrays.asList("UPDATE user_accounts SET bio='This is my bio' WHERE user_id = 1 OR name = 'Alex';",
"UPDATE user_accounts SET whereColumn='' WHERE user_id = 1 OR name = 'Alex'",
"UPDATE user_whereabouts SET columnName='' WHERE user_id = 1 OR name = 'Alex'");
for (String sql : sqls) {
Statement stmt = CCJSqlParserUtil.parse(sql);
Update update = (Update)stmt;
System.out.println("sql=" + stmt.toString());
System.out.println(" where=" + update.getWhere());
}
However you could improve your where search by using regular expressions, e.g. for with word boudaries:
\bwhere\b
but again you are right, this version is flawed as well for e.g. set col = ' test where test'.
The right way to do it, is to parse the whole sql via a parser (https://github.com/JSQLParser/JSqlParser).
This question already has an answer here:
How to retrieve sum of a column of data from the database?
(1 answer)
Closed 4 years ago.
Currently trying to get sum of the integers of a column called Cardhundred, I does not proceed the answer, can somebody suggest me an idea to get the total of all integers in my column?
I want to get the sum from a column in access database, the column from which I want to get the sum, has all integers value not double or float, and I have done some code for that which gives me no result, it means the text field which supposed to display the result is empty.
This is my code:
if(showtotal.isSelected()) {
try {
Connection conn = DriverManager.getConnection("jdbc:ucanaccess://E:\\Mydb.accdb");
Statement st = conn.createStatement();
String query = "SELECT sum(Cardhundred)FROM Dialog";
ResultSet rs=st.executeQuery(query);
if(rs.next()) {
String total=rs.getString("sum(Cardhundred)");
showdate.setText(""+total+"");
}
} catch(Exception e){ }
}
There are two ways to solve this: use the column index (rather than the name) then you don't need to worry about the name of the expression:
int total = rs.getInt(1);
The column numbering in JDBC starts with 1, not with 0 as with arrays in Java.
Alternatively, use a column alias in your query:
String query = "SELECT sum(Cardhundred) as total_number FROM Dialog";
Then use that alias to get the value:
int total = rs.getInt("total_number");
First of all I will explain my use case:
I will get a String Array of names from user(Can of size 2,5,1)
e.g Suppose user input is like this:
String[] names={"Micheal", "Joe","Jim"}
Now after taking input from user, I have to hit SQL table called "USERS" and check whether all of these names are present in USERS table or not. If any single name is not present then return false. If all names are present in USERS table then return true.
My Idea:
My idea is to hit USERS table. Get all names of USERS table in a String array (named as all_names) and then compare my input string(i.e names) with this all_names String. So if names is subset of all_names then return true else return false.
Problem:
But I think this is not an efficient solution. When this table will expand then I will have thousands of records so this technique will be very exhaustive. Any other better and efficient solution for this please.
Updated Solution:
Suppose names in USERS table are unique.
Thanks for your replies. Now I have adopted this approach after getting help from your answers. I want to know that this solution is a better approach or not:
String[] names={"Micheal","Jim","Joe"};
String list2string = StringUtils.join(names, ", ");
//connection was established previosuly
stmt = conn.createStatement();
System.out.println(list2string);
rs = stmt.executeQuery("SELECT COUNT(*) AS rowcount FROM USERS WHERE name IN (" +
list2string +
")");
rs.next();
int count = rs.getInt("rowcount");
rs.close();
if(names.length==count){
System.out.println("All names are in users table");
}else{
System.out.println("All names are not present in users table");
}
Want your comments on this updated solution please.
Regards
You are right, this is not really efficient.
It is the database job to do such things.
You can either make a select statement for each name, eg.
SELECT name FROM users WHERE name = 'Micheal'
or
SELECT name FROM users WHERE name IN ('Micheal', 'Joe', 'Jim')
and check the returned rows.
It might be quiet different depending on which framework you use to query the database.
you can form a string out of string array using loop
for example if you have string array like this:
String[] names={"Micheal", "Joe","Jim"}
get a string lets say s -> "Micheal", "Joe","Jim"
now query like this:
String sql = SELECT name FROM users WHERE name IN (" + s + ")". (you can check the format).
get the output collection and compare with the given collection.
One way to do it, could be
SELECT
COUNT(DISTINCT name)
FROM
users
WHERE
name IN ('Micheal', 'Joe', 'Jim')
Then check if the count is equal to your parameter count, in our case, we should get 3.
I will get a String Array of names from user(Can of size 2,5,1)
You get the input from user, you hit the database with query:
SELECT (WHATEVER_YOU_NEED) FROM SCHEMA_NAME.TABLE_NAME WHERE COLUMN IN
(USER_PROVIDED_INPUT);
You store this result in List.
Get all names of USERS table in a String array (named as all_names)
and then compare my input string(i.e names) with this all_names
String. So if names is subset of all_names then return true else
return false.
Yes, you are right, so you will use
Use Collection.containsAll():
boolean isSubset = listA.containsAll(listB);
And, if your database has unique names (which I guess can be duplicate), you can simply get the count from SQL Query and match it with the user input.
I hope this will help.
SELECT IF(
( SELECT COUNT(DISTINCT name) FROM users WHERE name IN ({toSearch}) ) = {Count},
, 1 , 0
) as Result
replace {toSearch} with e.g. 'Micheal', 'Joe', 'Jim'
{count} is the number of searche, in this example 3. so if all exist the column "Result" has the value 1 else 0
I have a simple model involving title and description. It extends play.db.jpa.Model
The following search method works perfectly
public static SearchResults search(String search, Integer page) {
String likeSearch = "%" + search + "%";
long count = find("title like ? OR description like ? order by " +
"title ASC", likeSearch, likeSearch).fetch().size();
List<Must> items = find("title like ? OR description like ? order by " +
"title ASC", likeSearch, likeSearch).fetch(page, 20);
return new SearchResults(items, count);
}
However when I tweak count as follows
long count = count("title like ? OR description like ? order by " +
"title ASC", likeSearch, likeSearch);
I get
PersistenceException occured :
org.hibernate.exception.SQLGrammarException: could not execute query
ERROR ~ ERROR: column "must0_.title" must appear in the GROUP BY
clause or be used in an aggregate function
Why is the error asking me to use an aggregate function when the query has not changed at all?
This is because in the first query, all the records are returned and then counted in the result list.
In your second query the count is done in the database so your sql must be formed correctly.
I think the order by is causing the error you described, try removing it. You are trying to order on column which are not part of the return (count return numbers not columns).
You can set the jpa.debugSQL=true in your application.conf if you need to see the sql generated.