What is the best way to get information from DB? - mysql

Which query is better to get data form more than two tables by id field? use one joins on one query or many select statements?
I want to get the run time optimal solution.
For example:
I have "tasks" table that include foreign keys fields,
like: statustask (from statustasks table), taskurgency (from taskurgency table)
whate is the best way to get the "tasks" list object form DB:
with joins:
String sql = "SELECT * FROM tasks "
+ "INNER JOIN statustask_in_language ON tasks.status=statustask_in_language.statustask_id "
+ "INNER JOIN statustasks ON tasks.status=statustasks.id "
+ "INNER JOIN taskurgency_in_language ON tasks.urgency=taskurgency_in_language.taskurgency_id "
+ "INNER JOIN taskurgency ON tasks.urgency=taskurgency.id ";
List<task> listUsers = jdbcTemplate.query(sql, new RowMapper<task>() {
#Override
public task mapRow(ResultSet rs, int rowNum) throws SQLException {
task t = new task();
tabelsTemplate status=new tabelsTemplate();
tabelsTemplate urgency=new tabelsTemplate();
t.setId(rs.getString("id"));
t.setDate(rs.getTimestamp("date"));
t.setTargetDate(rs.getTimestamp("targetDate"));
t.setSubject(rs.getString("subject"));
t.setDescription(rs.getString("description"));
t.setAdminId(rs.getString("adminId"));
t.setOpenedBy(rs.getString("openedBy"));
status.setId(rs.getString("status"));
status.setInCurrentLanguage(rs.getString("statustask_in_language.description"));
status.setDescription(rs.getString("desc"));
t.setStatusObj(status);
urgency.setId(rs.getString("urgency"));
urgency.setInCurrentLanguage(rs.getString("taskurgency_in_language.description"));
urgency.setDescription(rs.getString("descUrgency"));
t.setUrgencyObj(urgency);
return t;
or use one join and select statments for each foreign key to set the object.
note: In Task object the foreign keys are objects (not Ids).
thank you!

This is a very general question, and can't be correctly answered with out the proper information like an example.
Every thing depends on which information you want, and what you want to do with it.
If you are required to get data from multiple tables, JOINS is the way to go, since it's the easiest way to connect data to each other without actually needing to do some unnecessary logic.
In most cases - JOIN will be the correct way, but then again, there are cases where the logic to align the data with PHP for example will be hard , and separate queries can be easier to use.

Related

multi-tenancy Join or multiple Select queries postgres

I am implementing multi tenancy using single database and separating data for each tenant using a tenant_id. This id is passed in the jwt token as well. I have two tables right now genre and books. genre table has columns like
tenant_id, genre_id, ..... and books table has columns genre_id, book_id, book_name, ....
So 1 genre can have multiple books associated with it and 1 tenant can have multiple genres associated with it.
Now every time a book is fetched or updated I want to make sure the right person is making these calls.
I know of two ways to do it.
First way:
Make two queries. First fetch the book, get the associated genre_id in the object. Then fetch that genre and compare the jwt tenant_id with the tenant_id inside this genre object.
Something like this
const book= await ReadBook(req.query.book_id); // fetches my book from db
const genre = await ReadBook(book.genre_id); // fetches the genre from db
if (genre.tenant_id === jwtToken.tenant_id) {..} // compare if same or not
Second way:
Do this query in db
select b.*, g.tenant_id as tenant_id
from book_data b, genre_data g
where b.book_id = '0eokdpz0l' and g.tenant_id = 'M1MzgzMDM' and b.genre_id = g.genre_id
Which method is more efficient?
If theres a more efficient method then these then please let me know too
It's good practice to stick to ORM abstraction if possible, while minimising how much and how often data is transferred to/from db. Sequelize is able to construct an equivalent to that query for you, with the necessary joins and filters on the ids. Something among the lines of:
Books.findAll({
where: {book_id: '0eokdpz0l'},
include: [{
model: Genre,
where: {tenant_id : jwtToken.tenant_id}
}]
}).then(books => {
/* ... */
});
Running multiple queries in sequence not only adds latency due to additional round trips to/from db (and possibly connection setup if you're not pooling or holding them open) but it's also moving more bytes of data around, needlessly. tenant_id mismatch on db would send back a shorter message with an empty result. Checking it on client side requires downloading data even when you'll have to discard it.

How to get the results from multiple tables join using single query in Spring Data JPA?

I have to fetch the data from multiple tables by joining them using NativeQuery like below:
String query = "Select ad.* from address_data ad inner join address a ON a.ad_id = ad.ad_id where address = :address";
Query q = entityManager.createNativeQuery(query, AddressData.class);
q.setParameter("address", address);
List<AddressData> permitList = q.getResultList();
On testing the code, 2 queries are created to fetch the data.
to get the data from address_data table
to get the data from address table
How can I get only one query to fetch the data ?
In most cases you want your relationship to be lazy fetched fetch=FetchType.LAZY so your list is only loaded when you explicitly call it.
With that being said you can initialize a lazy association this way:
#Query("select ad from address_data ad inner join fetch a.addresss a where a.address = :address")
List<AddressData> methodName(#Param("address") String address);
There is no need of a native query for this. You can define a repository for your Entity and add the above method to it.
Here's a more detailed explanation on Fetch Strategy.
You also might want to check the Spring Data JPA documentation on repositories.
BTW you should post your Entities as well.

correctly fetch nested list in SQL

I have a design problem with SQL request:
I need to return data looking like:
listChannels:
-idChannel
name
listItems:
-data
-data
-idChannel
name
listItems:
-data
-data
The solution I have now is to send a first request:
*"SELECT * FROM Channel WHERE idUser = ..."*
and then in the loop fetching the result, I send for each raw another request to feel the nested list:
"SELECT data FROM Item WHERE idChannel = ..."
It's going to kill the app and obviously not the way to go.
I know how to use the join keyword, but it's not exactly what I want as it would return a row for each data of each listChannels with all the information of the channels.
How to solve this common problem in a clean and efficient way ?
The "SQL" way of doing this produces of table with columns idchannel, channelname, and the columns for item.
select c.idchannel, c.channelname, i.data
from channel c join
item i
on c.idchannel = i.idchannel
order by c.idchannel, i.item;
Remember that a SQL query returns a result set in the form of a table. That means that all the rows have the same columns. If you want a list of columns, then you can do an aggregation and put the items in a list:
select c.idchannel, c.channelname, group_concat(i.data) as items
from channel c join
item i
on c.idchannel = i.idchannel
group by c.idchannel, c.channelname;
The above uses MySQL syntax, but most databases support similar functionality.
SQL is made for accessing two-dimensional data tables. (There are more possibilities, but they are very complex and maybe not standardized)
So the best way to solve your problem is to use multiple requests. Please also consider using transactions, if possible.

serializing parent/child relationships with newtonsoft.json and linq to sql

I am having a problem. I have a table tblitems which has a primary key which has a child table tblweeks linked via foreign key. When using json.net to serialize json, even when the reference loop handling is set to referenceloophandling.ignore, it is serlilizing the parent tblitem class for every tblweekof linked to it. I don't want that but I still want some fields from the child class. Is there a way in my linq query to only select some columns from a child table or do I have to break the relationships? I'm confused, this seems like really unexpected behavior.
UPDATE
OK, I kind of have what I want now, I found I could use the select function on the child table to only select certain columns, but what is the best way to garentee the order of the child records? I want to make sure they are ordered by weekof in this example:
var q = from lineITem in db.tblBroadcastEntryItems
where lineITem.broadcastID == Int32.Parse(context.Request.QueryString[0])
select new
{
...,
week = lineITem.tblBroadcastEntryWeeks
.Select(c => new { c.weekof, c.spots, c.id })
};

Querying many to many relationship with LinqToSQL

I have a database setup as follows (unfortunatelly was not allowed to publish diagram image in here so need to describe:
Responses table - contain RespondentID, QuestionID, ResponseOptionID
ResponseProperties - contain ResponsePropertyID, ResponsePropertyTypeID, Name
ResponsePropertyTypes - contain ResponsePropertyTypeID, Name
ResponsesInProperties (a many to many table) - contains ResponseID, ResponsePropertyID
There is a many to many relationship on ResponsesInProperties table. This table does not show in EF of course.
Say I have two response property types "Country" and "Wave" and corresponding ResponeProperties "USA", "UK" and "Wave2011", "Wave2012".
Now I need to get back from the database all (and not duplicated) responses that would be in USA and also in Wave2012. The trick is that every response I need must be in both Wave2012 and USA. I am trying to achieve this with LINQ to SQL. The below is Linq I came up with that get's me the correct records but they appear many times for different properties. Limiting the properties gives me no records whatsoever....
Any help appreciated!
var responses = from r in db.Responses
from rp in r.ResponseProperties
select new
{
RespondentID = r.RespondentID,
QuestionCode = r.Question.Code,
ResponseOptionCode = r.ResponseOption.Code,
ResponseOptionCodeName = r.ResponseOption.Text,
ResponsePropertyName = rp.Name,
ResponsePropertyTypeName = rp.ResponsePropertyType.Name
};
To clarify, you are trying to do this with LINQ to SQL and not EF as they have rather different models for M-M. With LINQ to SQL, you do have to include the middle join table.
The key thing missing from your query at this point is the filter (Where) clauses. You need to specify them for both sides of the join to properly filter the results. You indicate that when you supply a filter you get back no records. Can you clarify your question with that filter as it may help to fix your underlying problem.
Your query cannot produce unique responses because you also get ResponsePropertyName and ResponsePropertyTypeName, which will duplicate the results.
This entity framework query -
from r in db.Responses
where r.ResponseProperties.Any (rp => rp.Name == "USA")
where r.ResponseProperties.Any (rp => rp.Name == "Wave2012")
select new
{
RespondentID = r.RespondentID,
QuestionCode = r.Question.Code,
ResponseOptionCode = r.ResponseOption.Code,
ResponseOptionCodeName = r.ResponseOption.Text,
};
does produce unique Responses that are in USA and in Wave2012. The produced sql will show two EXISTS predicates with AND.