Facilitate SQL table query functionality in Java application [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Say I have a couple of columns say First Name, LastName, Email, Phone.
I want to query for a row based on a dynamic column selection.
Say the application will ask for a record based on 1) lastname and phone or 2) FirstName 3) Phone and Email
Instead of creating a table to do a SQL query to find a row based on the column data is there a data structure which suits my needs? I am coding in Java, so if there is an inbuilt API please suggest one
FirstName | LastName | Email | Phone
abc | xyz | abc#m.com | 123
pqr | qwe | pqr#m.com | 342
ijk | uio | ijk#m.com | 987

I'd point you to any of the available in memory SQL Db libraries:
H2
Derby
HSQL
Or maybe you want an indexable, queryable in-memory store:
Hazelcast
Ehcache
Any one of these allows you to write a query against the data stored.

If you want to have the information loaded into memory and available for multiple queries, I would use a lookup structure using a Map (e.g. a HashMap) and ArrayList.
Note: If your only going to query once, I would do it directly in the look when reading the lines.
EG: HashMap<String, ArrayList<wordLocation>> lookup= new HashMap<String, ArrayList<wordLocation>>();
Example:
import java.util.ArrayList;
import java.util.HashMap;
public class WordLookup {
public static void main(String args[]) {
WordLookup wl = new WordLookup();
String[] simulatedFileRows = new String[5];
simulatedFileRows[0] = "cat,dog";
simulatedFileRows[1] = "hen,dog";
simulatedFileRows[2] = "cat,mouse";
simulatedFileRows[3] = "moose,squirrel";
simulatedFileRows[4] = "chicken,rabbit";
String columns[];
String row;
int column = 0;
for(int i=0; i<simulatedFileRows.length; i++) //Simulated readline
{
row = simulatedFileRows[i];
columns = row.split(",");
column=0;
for(String col:columns)
{
column++;
wl.addWord(col, i, column);
}
}
//Where is moose?
ArrayList<wordLocation> locs = wl.getWord("moose");
if(locs!=null)
{
System.out.println("Moose found at:");
for(wordLocation loc: locs)
System.out.println("\t line:"+ loc.line + " column" + loc.column);
}
}
private HashMap<String, ArrayList<wordLocation>> lookup= new HashMap<String, ArrayList<wordLocation>>();
public void addWord(String word, int line, int column)
{
ArrayList<wordLocation> wordLocArr = lookup.get(word);
if(wordLocArr == null)
{
wordLocArr = new ArrayList<wordLocation>();
lookup.put(word,wordLocArr);
}
wordLocArr.add( new wordLocation(line, column));
}
public ArrayList<wordLocation> getWord(String word)
{
return lookup.get(word);
}
class wordLocation{
public int line, column;
public wordLocation(int l, int c)
{this.line = l; this.column = c;}
}
}

suppose you have something like HashMap map for field=>value
then you can do (if you dont want to query with value, you can take out the where statement)
if(map.size()>0){
String whereStatement = " 1=1 ";
String selectStatement = " ";
for(String field : map.keySet()){
whereStatement+= " AND "+ field+"="+map.get(field);
selectStatement+= field+",";
}
selectStatement.replaceLast(",", "");
String query = "SELECT " + selectStatement + " FROM sometable " + whereStatement;
}

If you don't index the columns in an SQL DB, that's roughly equivalent to simply having an array, where each element corresponds to a row.
If you do index the columns, that's about the same as additionally having something like a TreeMap (of string or integer or some collection of objects, depending on the type of the fields, to array index) for each index (at least based on my somewhat limited knowledge of the underlying structure of DBs - actually I think databases typically use b-trees, but there isn't a b-tree structure in the standard Java API to my knowledge).
Actually a TreeMap to array index isn't sufficient for non-unique indices, you'll have to have a TreeMap to a list of array indices, or a MultiMap (not in the standard API).
If you don't have an index for any given query, you'll have to iterate through all the rows to find the correct one. Similarly, you'll have to iterate through the whole array to find the correct element.
So, if you only want to query single columns (and do so efficiently), and this can be any of the columns, you'll have to have a TreeMap (or similar) for each column, and an array or similar as a base structure.
If, however, we're talking about querying any combination of columns, you're unlikely to get a particularly efficient generic solution, as there would simply be too many combinations to have a structure for all of them, even for a small number of columns.
Note: I say TreeMap as opposed to HashMap, as this is closer to how databases actually work. If the types of queries you're running doesn't require sorted data, you could happily use a HashMap instead.

Related

Querying mysql with java with multiple possible "where" statements

I'm trying to find a nice solution to a movie filtering system built in java and with a mysql database. The user is supposed to be able to filter which movies they wish to see based on a number of attributes, such as: director, actor, length, genre, year,...,. In total there are 11 fields which can be used to filter the query.
The problem is some of these fields can (and probably will) be left blank. For instance, maybe the user only wants to filter data based on a certain genre, director and length. Or maybe they only want to filter it based on the prodution studio, and dont care about the other filter options.
I have made a connection to the server, and the problem is in creating the "SQL_String" that I will use in statement.executeQuery(SQL_String).
Lets say I only wanted to filter for one field. Then I know I could write
String field = //user input (for example: actor)
String filter = //user input (for example: 'tom cruise')
String SQL_String = "SELECT * FROM Movies WHERE "+field + "=" +filter
But if i want to allow the user to filter based on several (or zero) fields, then I dont know how to write the code.
Some example queries could be:
"SELECT * FROM Movies WHERE (director = 'steven spielberg' AND genre = 'action' AND length >100)"
"SELECT * FROM Movies WHERE (type = 'tv-series' AND actor = 'bob odenkirk')"
So the user can specify which fields they want to filter (if any) and i need to come up with a java code that can take those into account and construct a query string.
Since you don't know how many fields the user will filter on but you do know that the data you're dealing with has two parts (the field and the filter), the first two things that come to my mind are maps and tuples. Since, unlike Python, Java does not have a built in tuple data type (to my knowledge), here is a small example solution that I thought of for your problem solved using Java's HashMap and Map classes.
In this example, I create a HashMap with the key being a string for the "field" and the value being a string for the "filter". You can set these values based on the user input wherever you have that in your code (in this example, simply hard-coded in the main method). Then you can loop through the key-value pairs in your HashMap (see this helpful post), appending the key and value as well as the additional characters necessary for the query. This is a simple example but shows a possible solution route.
If you want to make sure that this solution works for the cases where you filter value is an integer, then just add in another if-statement in the loop to try parsing for an integer and if one exists to not add the extra \' escape characters.
import java.util.HashMap;
import java.util.Map;
public class MovieQueryTest {
public static void main(String[] args) {
String SQL_Query = "SELECT * FROM Movies WHERE ";
HashMap<String, String> queryFilters = new HashMap<>();
queryFilters.put("director", "Steven Spielberg");
queryFilters.put("type", "tv-series");
queryFilters.put("actor", "Bob Odenkirk");
boolean firstQueryFilter = true;
for (Map.Entry<String, String> entry : queryFilters.entrySet()) {
if (firstQueryFilter) {
SQL_Query += entry.getKey() + "=\'" + entry.getValue() + "\'";
firstQueryFilter = false;
} else {
SQL_Query += " AND " + entry.getKey() + "=\'" + entry.getValue() + "\'";
}
}
System.out.println(SQL_Query);
}
}

How to select a particular hashmap<String,String> from a list by its value

I'm fairly new to Java and have been searching everywhere for an answer.
I run a sql query and use the response to build a list of hashmaps from the column name and values.
List<HashMap<String,String>> rulesList = Sql.getStuff("abc");
This gets me a list like this {column_1=abc, column_3=ghi, column_2=def}
I want to do two things with this list. First off I want to see if any column contains a particular value (ruleName). This part decent enough.
if (rulesList.get(0).containsValue(ruleName)) {
System.out.println("Expected: " + ruleName);
System.out.println("Actual: " + ruleName); //Would like to change this to include the actual column name and result
Then I want to check all the other columns that have a particular phrase in their name to see if they contain a value or not, such as the word "column" from "column_1, column_2, column_3". If they do contain the value then I want to print out the column name and value.
However, this is when I run into the problem of not knowing how to select from within the list. How can I get only column_2 and its accompanying data, or the column name associated with value abc?
something like this example?
List<HashMap<String,String>> rulesList = new ArrayList<HashMap<String,String>>() {{
for (int i = 0; i < 4; i++) {
HashMap<String,String> map = new HashMap<>();
map.put("key", Integer.toString(i));
map.put("column1", "Value in Column1 in row " + i);
map.put("column2", "Value in Column2 in row " + i);
add(map);
}
}};
for (HashMap<String,String> row : rulesList) {
for (String columnName : row.keySet()) {
// look for a column name
if(columnName.contains("column")) {
System.out.printf("Column \"%s\" has a value of \"%s\"%n", columnName, row.get(columnName));
}
// look for a cell value
if(row.get(columnName).matches(".+Column\\d in row 1")) {
System.out.printf("Value found in %s, row %s%n", columnName, row.get("key"));
}
}
}
I think you just need vocabulary : a hashmap associates a key (unique) with one value.
So with that keywords in mind you can easily find answer, like :
First off I want to see if any column contains a particular value (ruleName)
Here is an example
Then I want to check all the other columns that have a particular phrase in their name to see if ...
And there.
your question is premised around a list of hashmaps
Based on your question, it looks like you might be trying to use this structure:
List_Row<HashMap<String_ColumnName, String_Value>>
If this is the case, consider modifying your storage structure and storing a hashmap each with a list:
HashMap_ColumnName<ArrayList<String_Values>>
then you can simply grab a column and look through data. to get the row back as a list, you can write a function to do that pretty easily
getRow(i) {
HashMap<String,String> row = new HashMap<String,String>()
for(k:results) {
row.put(k, results.get(k).get(i))
}
return row
}

Get individual values from an array created from a resultset in java

I have an array that was created from an ArrayList which was in turn created from a ResultSet. This array contains rows of database table and each row (with several columns based on my query) exists as a single element in the array. So far so good. My problem is how to get individual values (columns) from each row which, I said earlier, now exists as an element. I can get each element (row, of course) but that is not what I want. Each element is a composite of several values and how to get those? I am a beginner and really stuck here. I think this all make sense. Here's the code how I created the array.
List resultsetRowValues = new ArrayList();
while (resultSet.next()){
for (int i = 1; i <= columnCount; i++) {
resultsetRowValues.add(resultSet.getString(i));
}
}
String[] databaseRows = (String[]) resultsetRowValues.toArray(new String[resultsetRowValues.size()]);
EDIT: More explanation
My MySQL query is as follows:
String query = "SELECT FIRSTNAME, LASTNAME, ADDRESS FROM SOMETABLE WHERE CITY='SOMECITY'";
This returns several rows in a ResultSet. And according to the sample query each element of an array will cotain three values (columns) i.e FIRSTNAME, LASTNAME and ADDRESS. But these three values exist in the array as a single element. While I want each column separately from each element (which is actually a row of the database table). When I iterate through the aarray using for loop and print the values to the console, I get output similar to the following:
Doe
Jhon
Some Street (End of First element)
Smith
Jhon
Some Apartment (End of Second element and so on)
As it is evident from the output, each element of the contains three values which are printed on separate lines.
How to get these individual values.
You probably want something like that:
List<Map<String, String>> data = new ArrayList<>();
while (resultSet.next()){
Map<String, String> map = new HashMap<>();
for (int i = 1; i <= columnCount; i++) {
map.put("column" + i, resultSet.getString(i));
}
data.add(map)
}
// usage: data.get(2).get("column12") returns line 3 / column 12
Note that there are other possible options (2D-array, guava Table, ...)

Group by functionality in Java

I am trying to write a Java program that loads the data (from a tab delimited DAT file) and determines the average amount in Euros (EUR), grouped by Country and Credit Rating.
I have 2 questions,
what is the best way to load the data into data structure after spliting into array?
How do i approach about providing group by functionality in Java
Update: I have given a first try and this is how implementation looks like. Feels like there is a room for improvement.
/**
* #param rows - Each row as a bean
* This method will group objects together based on Country/City and Credit Rating
*/
static void groupObjectsTogether(List<CompanyData> rows) {
Map<String, List<CompanyData>> map = new HashMap<String, List<CompanyData>>();
for(CompanyData companyData : rows){
String key;
if(companyData.getCountry().trim().equalsIgnoreCase("") || companyData.getCountry() == null){
key = companyData.getCity()+":"+companyData.getCreditRating(); //use city+creditRating as key
}else{
key = companyData.getCountry()+":"+companyData.getCreditRating(); //use country+creditRating as key
}
if(map.get(key) == null){
map.put(key, new ArrayList<CompanyData>());
}
map.get(key).add(companyData);
}
processGroupedRowsAndPrint(map);
}
It all depends on the amount of data and performance (CPU vs memory) of the machine. It the amount of data is not significant (less than millions of records or columns) and the number of columns is fixed then you may simply put all data in arrays using
String[] row = String.split(";");
which shall split each row using ; as delimiter. Then you may achieve your grouping functionality using HashMap, i.e.:
ArrayList<String[]> rowAr = new ArrayList<String[]>();
HashMap<String,ArrayList<Integer>> map = new HashMap<String,ArrayList<Integer>>();
int index = 0;
for (String rowStr: rows) {
String[] row = rowStr.split(";");
rowAr.add(row);
String companyCode = row[0];
//please keep in mind that for simplicity of the example I avoided
//creation of new array if it does not exist in HashMap
((ArrayList<Integer>)map.get(companyCode)).add(index);
index++;
}
Sorry for any syntax or other simple errors above (I do not have any tools in hand to verify if there is not any stupid mistake).

How to code a Closest Match String search in a database query in Java?

My specific problem is related to an Android project but this is not a specific android question.
I am basically just trying to come up with a way I can query a database and return results not based on exact matches but based on similar terms even outside the scope of a search on whether a String "contains" the typed value.
So for example, lets say I have a entry called "Popeye's Catfish". And lets say somebody enters the term "P's CatSalmon" and are looking for that entry. I would like to return a query list that shows essentially a "most similar" match.
I admit I am a complete novice at database queries so there might be ready answers out there that I just can't find (I did look). There are a few ways I can think to do this:
I could break apart the search string and look for separate parts of each string in a "contains" search of the actual entry. For example I could break out "P" "Cat" and "Salmon" search all three and do some other code to find out what the best result is. However, I'm really not sure how I would code it so that the program could pick the best segments. How would it know to pick out "cat" for example without just iterating through every possibility (which is almost certainly not realistic)?
I could just let the users suffer for a while until tags exist. What I mean is, once the correct entry is found by the "proper" name, I could just let users tag it with associated names and then include that separate associated name in the search by later users.
I can't come up with anything better than that based on my current level of knowledge.
Thanks in advance for the help.
I'm guessing that this is some sort of find location app. So let's assume that the number of locations is small, say less than 200.
You would start by building a search that looks for the "words" that the user typed in the locations. In your example, we have "P's" and "CatSalmon". "CatSalmon won't match anything, and neither will "P's".
So you return something that looks like this:
Locations found for "P's CatSalmon"
-----------------------------------
No locations found. Try using different search terms.
So, our user types "P CatSalmon".
So you return all the locations that start with the letter P, then the locations that contain the letter P.
Something like this:
Locations found for "P CatSalmon"
---------------------------------
Popeye's Catfish
Public library
Hope Restaurant
...
Now, here's where it gets interesting.
When the user picks a location, you log the search term and the location selected.
In your example, the user would pick "Popeye's Catfish".
So later, you manually add this key value to a synonym map.
Key Value
--------- ----------
CatSalmon Catfish
Over time, your searches will get better because your users will define the synonyms.
So, to recap.
You search for locations that start with a word.
You search for locations that contain a word.
You look in the synonym map for synonyms, and you repeat the start / contain process with the synonym(s).
Start locations are displayed first, then contain locations.
Finally, you do all this work on the server with the database. You pass the sorted location list to the phone. Don't make the phone do all the work.
This is something I put together essentially highlighting the closest matched term with a query based on the number of sequential characters
public class SequenceMatches {
public static void main(String [] args)
{
HashMap<String, Integer> map = new HashMap<String, Integer>();
String query = "P's SalmonCat ";
map = addTermsToHashMap(map);// add terms to a hash map
map = compareFirstCharacter(map, query);// compare the initial first character
map= compareSequentialCharacters(map, query);// compare terms to query and add score based on the number of matches
printResults(map);
}
public static HashMap<String,Integer> addTermsToHashMap(HashMap<String,Integer> map){
String term = "Popeye's CatFish";
String otherTerm = "Popets CatSalmon";
map.put(term,0);
map.put(otherTerm,0);
return map;
}
public static HashMap<String,Integer> compareFirstCharacter(HashMap<String,Integer> map,String query){
for(Map.Entry<String,Integer> e: map.entrySet())
{
String term = e.getKey();
char [] termChar = term.toCharArray();
char [] queryChar = query.toCharArray();
if((queryChar[0]) == (termChar[0]))
{
int value = map.get(term);
map.put(term,++value);
}
}
return map;
}
public static HashMap<String,Integer> compareSequentialCharacters(HashMap<String,Integer> map,String query){
for(Map.Entry<String,Integer> e: map.entrySet())
{
String term = e.getKey();
char [] termChar = term.toCharArray();
char [] queryChar = query.toCharArray();
for(int i = 0; i < queryChar.length -1; i++)
{
for(int j = 0; j < termChar.length -1; j++)
{
if(queryChar[i] == termChar[j] )
{
if((queryChar[i + 1]) == (termChar[j + 1]))
{
System.out.println((queryChar[i + 1]) + " " + (termChar[j + 1]));
int value = map.get(term);
map.put(term,++value);
break;
}
}
}
}
}
return map;
}
public static void printResults(HashMap<String,Integer> map)
{
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
}

Categories