Design a system java same as relational database.
For example,
You Have employee table as below:
ID | Name | Manager | Salary
Now you can execute queries like :
select * from Employee where ID= ' something'
select * from Employee where Name= ' something'
select * from Employee where Name= ' something'
In same way you have a class Employee as bellow:
class Employee{
String ID;
String Name;
String Salary;
String Manager;
}
Now I want to query on this class as same as the SQL queries above,
How can I do it efficiently?
The code should be optimized on time complexity and space complexity.
In Java you have collections like List or Set which could be thought of as a Table or Rows.
You also have Map which acts like an unique index, and NavigableMap which works like a unique sorted index. There is also MultiMap which is like a non-unique index.
Related
How can i write dynamic SQL query in Jbdi, like in my project customer will ask some details like first name,last name,mobile. so i will read those values into string and my idea was directly append that to SQL query dynamically like
select first name,last name,mobile from customer
and another user ask only first name then my query will change like
select first name from customer where customer Id=12345
I am doing something similar for dynamically generated search criteria strings in a Dropwizard application using JDBI.
#UseStringTemplate3StatementLocator
public interface ThingieDao {
#SqlQuery
#MapResultAsBean
Iterator<Thingie> search(#Define("criteria") String criteria);
}
The defined string "criteria" can then be used in the SQL template:
group ThingieDao;
search(criteria) ::= <<
SELECT * FROM table_name WHERE <criteria>
>>
You can use the same technique to insert any string in the SQL, the SELECT column names in your case.
The variable name in the interface does not matter, it is the #Define annotation string that matters.. Assuming Dropwizard doesn't add anything magic, and it usually doesn't, I guess that should work using plain JDBI as well.
We would typically write Oracle SQL to find max salary of every employee in each department if we had a table with EmpID, DeptID, Salary:
select EmpID,DeptID, rank over(partition by DeptID order by Salary) rnk
from Table
where rnk=1;
OR
select EmpID
from Table1
where Salary =(Select max(Salary) from Table2 group by DeptID
and Table2.DeptId = Table1.DeptId )
If the above table was a file instead, then how can we write custom Java code to implement the same behavior?
If I got your question right, why don't you implement it by reading the file and passing it to the library of your choice for querying? Or by using Hibernate, and then passing the read file as:
Session.createSQLQuery(fromReadFile)
and
Session.createSQLQuery(fromReadFile).uniqueResults()
to get the results as a List or a particular object?
We have the following (poorly designed?) table:
inputs:
keyword_id serial not null,
group_name string not null,
banned_term string not null
Keyword ID is the primary key. there are many banned terms per group_name. The data looks like this:
keyword_id | group_name | banned_term
1 | incentivization | free money
2 | inaccuracy | we're number one
3 | incentivization | win a free ipod!
There's no join table, and group_name isn't its own entity. I'd like a domain object something like this:
class BannedTermGroup {
Integer id;
String group_name;
Set<String> banned_terms;
// ... various getters and setters
}
The only examples on this one-to-many relationship between the group name and banned terms all involve some sort of join column or join table, while group_name would always be part of some other entity. Here neither is the case. Can this be mapped using Hibernate?
As quoted in my previous comment, you can get the ID of the group from nowhere.
Just to put aside this problem, you may look into Hibernate's reference, search for collections of basic types. It is what you need.
However, you still need to have a table for the "group".
assume it is as simple as a one column table:
KEYWORD_GROUP
--------------------
GROUP_NAME STRING
Your original keyword table:
KEYWORD
--------------------
GROUP_NAME STRING
KEYWORD STRING
I believe this is what you need:
#Entity
#Table("KEYWORD_GROUP")
public class KeywordGroup {
[.....]
#ElementCollection
#CollectionTable(name="KEYWORD", joinColumns=#JoinColumn(name="GROUP_NAME"))
#Column(name="KEYWORD")
private List<String> keywords;
}
For the keyword_group table, you probably don't need to create a new table if you are just using this model for read. Create a view from your original keyword table should be good enough.
I have an employee table like:
Empid EmpName Remark
001 Bob
002 Harish
003 Tom
004 Dicky
001 Bob
003 Tom
I have to find the duplicate employee id and accordingly updating the remark field as duplicate !
Thanks.
update employee set remark = 'duplicate'
where empid in (
select empid
from employee
group by empid, empname
having count(*) > 1 )
This question is very vague, because you do not mention what ORM library you are using or how you are accessing/manipulating your database. But basically want you want to do is execute a derived table query, then make a decision based on the results.
SELECT * FROM
(SELECT empId, count(empId) numIds from Employee group by empId) IdCount
WHERE numIds > 1;
Run this query via a PreparedStatement or whatever your ORM framework provides, then iterate over each result and update your remark field.
Below will give you ID of duplicate records
`select empID, empName, count(empID) as cnt from fschema.myTable group by (empID) having cnt > 1 order by cnt`
Will get back to you how to set remark as 1 for duplicates shortly...
is there someway we can group similar data in java?
i want to group all the data with same id and print it out.
i am querying for the data using jdbc and was searching for a library i could use for this.
any idea?
thanks
Use a Map<GroupID, List<Data>>.
Map<Long, List<Data>> groups = new HashMap<Long, List<Data>>();
while (resultSet.next()) {
Long groupId = resultSet.getLong("groupId");
String col1 = resultSet.getString("col1");
String col2 = resultSet.getString("col2");
// ...
List<Data> group = groups.get(groupId);
if (group == null) {
group = new ArrayList<Data>();
groups.put(groupId, group);
}
group.add(new Data(groupId, col1, col2 /* ... */));
}
You could also just make it a property of another (parent) bean.
See also:
Collections and Maps tutorial
Ideally you should use a where clause in your SQL query to limit the returned data to the id in question:
select *
from table
where id = 'xxxxxx'
Of course if you will be printing out the data for all id's this may be a bad choice, as then your app will perform multiple sql queries, which usually will result in a performance hit.
As for grouping data in Java, take a look at java.util.HashMap (or any of the container classes that implement the Map interface). HashMap is a container of key-value pairs. In your case, the 'key' can be a String (or whichever data type applies) representing your id, and the 'value' can be an object to contain the data associated to the id key (i.e.: ArrayList of Strings, or a new class you define to help you manage the data)
Are you looking for the SQL ORDER BY clause?
SELECT columns
WHERE criteria
ORDER BY id ASC;
That will give you all the data in your criteria and will order it by the id column which naturally means that all the rows with the same id will appear consecutively.