Select from two tables and create object with data - mysql

I'm trying to fetch data from two MySQL tables and push each into array.
I have to tables item and user with the same column - item_id. Now im requesting the data from them with
var query = "SELECT * FROM items, users WHERE items.item_id=?";
query = connection.format(query,req.params.item_id);
After this, im getting a wall of data. Like this:
{
{ user_id: 13213,
user_name: 'John',
item_id: 1337,
item_name: Leet stuff,
item_price: 13,37
},
{ user_id: 12345,
user_name: 'Mike',
item_id: 1337,
item_name: Leet stuff,
item_price: 13,37
}
But what I actualy need is this:
{
users: [
{ user_id: 13213,
user_name: 'John'
},
{ user_id: 12345,
user_name: 'Mike'
}
],
item_id: 1337,
item_name: Leet stuff,
item_price: 13,37
}

You can't do that in a single query. However, you can use two different queries and combine the output, e.g.:
SELECT u.user_id, u.user_name
FROM users u JOIN ITEMS i ON j.user_id = i.user_id
WHERE i.item_id = ?;
This will give you the list of users. You can then use the below query to get the item details:
SELECT item_id, item_name, item_price
FROM items
WHERE item_id = ?
You can then construct the required structure in your application.

Related

Count multiple associated models in sequelize

I have 3 models defined, Companies, Projects and Users.
Companies has many Projects and Users, so Projects and users has one company.
The problem that i am facing is when i try to count how many users and projects a company has, i get wrong results, somehow querying multiple associations is modifying the value of each other.
This is the models association:
CompaniesModel.hasMany(AppUsersModel)
AppUsersModel.belongsTo(CompaniesModel)
CompaniesModel.hasMany(ProjectsModel)
ProjectsModel.belongsTo(CompaniesModel)
This is where i try to query the count of Users and Projects for each Company:
const companiesInfo = await models.companies.findAll({
attributes: {
include: [
[sequelize.fn("COUNT", sequelize.col("projects.id")), "projectsCount"],
[sequelize.fn("COUNT", sequelize.col("app_users.id")), "usersCount"],
],
},
include: [
{ model: models.projects, attributes: [] },
{ model: models.app_users, attributes: [] },
],
group: ['companies.id']
})
SQL Query produced:
SELECT `companies`.`id`, COUNT(`projects`.`id`) AS `projectsCount`, COUNT(`app_users`.`id`) AS `usersCount` FROM `companies` AS `companies` LEFT OUTER JOIN `projects` AS `projects` ON `companies`.`id` = `projects`.`companyId` LEFT OUTER JOIN `app_users` AS `app_users` ON `companies`.`id` = `app_users`.`companyId` GROUP BY `companies`.`id`
With this query i expected to get an array of companies like this:
[
{name: companyX, usersCount: 1, projectsCount: 2},
{name: companyY, usersCount: 5, projectsCount: 1},
...
]
But what i am getting is almost what i want but for some reasons the values are being multiplied by each other, for example:
[
{name: companyX, usersCount: 2, projectsCount: 2},
{name: companyY, usersCount: 5, projectsCount: 5},
...
]
This is what i get event though companyX only has 1 user and companyY only has 1 project, but it seems to me that, in the case of companyX, usersCount is being multiplied by projectsCount.
For instance if companyX has 2 users and 2 projects i will get the following results:
[
{name: companyX, usersCount: 4, projectsCount: 4},
...
]
I would be grateful for any insight in to a solution for this.
You need a distinct count if you are counting 2 columns in the same query.
include: [
[sequelize.fn("COUNT", sequelize.fn("DISTINCT", sequelize.col("projects.id"))), "projectsCount"],
[sequelize.fn("COUNT", sequelize.fn("DISTINCT", sequelize.col("app_users.id"))), "usersCount"],
],

Fetching TypeORM data with limit and order by and child relationship with getMany()

I need a help with nestjs typeorm query. Scenario is as follows
Suppose i have 3 tables say Teachers, Students and Parents
Teachers = One to many relation w.r.t Students , i.e one teacher can
teach multiple students.
Students = Many to one relation w.r.t
Teachers.
Students = One to Many w.r.t Parents , assuming 1 child
of Parents
Parents = Many to One w.r.t Students
const records = await this.createQueryBuilder('teachers').leftJoinAndSelect('teachers.students', 'students').leftJoinAndSelect('students.parents', 'parents').orderBy('teachers.id', 'DESC').limit(1);
let res = await records.getMany();
output something like this
{
teacher_id: '4',
teacher_name: 'abc',
students: [
{
'id': 1,
'name': 'pqr',
status: 'failed',
parents: [
{
id: 1,
name: 'mom',
relationship: 'mom'
},
{
id: 2,
name: 'dad',
relationship: 'dad'
}
]
}
]
}
Let us say there are 100 teachers. Each teacher has 20 students and each student has 2 parents.
Total records which the query would return = 100 * 20 * 2 = 4000
But while showing the results in a paginated way we need to group records by teacher.id.
Total count using group by teacher.id = 100
Example code -
async getTeacher(): Promise<any[]> {
return await this.repo
.createQueryBuilder('teachers')
.leftJoinAndSelect('teachers.students', 'students')
.leftJoinAndSelect('students.parents', 'parents')
.groupBy('teachers.id')
.orderBy('teachers.id','DESC')
.limit(1)
.getMany();
}

How to store multiple values on a mysql table

I'm new to SQL and I try to understand some basic stuff.
I have 2 tables:
users: ID | NAME | EMAIL | APPS
apps: ID | NAME
QUESTIONS
How do I create a third table based on those two, that as a JSON will look like this:
[
{ id: 1, name: 'Daniel', email: 'dan#iel.com', apps: [1,2,3]},
{ id: 2, name: 'Ben', email: 'dan#iel.com', apps: [1,5]},
{ id: 3, name: 'Maya', email: 'dan#iel.com', apps: [4]}
]
Query wise, how do I write a query that create a user like this, where apps is a list of ID's:
{ id: 1, name: 'Daniel', email: 'dan#iel.com, apps: [1,2,3]}
would it not be better to use a pivot table.
pivot table:
[
{ pivot_id: user_id, app_id },
{ pivot_id: user_id, app_id },
]
a simple loop could be used to insert into pivot table
foreach(apps as app_id)
{
query = "INSERT INTO pivot_table set user_id = `user_id`, app_id = `app_id` ";
}

Retrive all the value that satisfy the condition of first table

I have two tables users and location. I need to join both tables
what i need is get all the area number of all the users which are present in the user table.
ie user 1 has 3 entries in the second table so i need to join the table in such a way that is,
id1 = 1
area = 2,3
area 2 is repeating so do not include it twice
i tried the join but now getting the correct way to doing it.
What i tried?
$location = User::
join('addresses','users.id1','=','addresses.id1') ->select('users.id1','addresses.area')
->get();
Expected Output
User 1 -> area ->2,3
Here are the two ways to do this.
Firstly you can use Laravel relationship:-
In your model User create relationship:-
function addresses()
{
return $this->hasMany(Address::class, 'id1', 'id1');
}
Now in your User controller you can get User addresses (areas) like this
$users = User::with('addresses')->get();
dd($users->toArray());
This will print something like this
[
{
id1: 1,
name: abaa
pwd: 12345
addresses: [
{
id2: 1,
id1: 1,
area: 2
},
{
id2: 2,
id1: 1,
area: 3
},
{
id2: 3,
id1: 1,
area: 3
}
]
},
{
...
}
]
Second you can use Laravel relationship:-
$builder = new User;
$builder->join('addresses','users.id1','=','addresses.id1')
->selectRaw("users.*, GROUP_CONCAT(DISTINCT addresses.area SEPARATOR ',') as distinct_areas")
->groupBy("users.id1")
->get();
This query will give you result something like this
[
{
id1: 1,
name: abaa,
pwd: 12345,
distinct_areas: 2,3
},
{
...
}
]
I think this will help you.

Get records with nested items node-mysql

Im using node-mysql for database query manpulation in my expressjs app, And I want to get a nested results from a query. But seems I can't find a way how to do it in a simple way.
In their document I found Joins with overlapping column names
which can query a table name and nested with a columns. However this
is not suitable work around for one-to-many or many-to-many structure.
Following are examples of table structure and expected results .
Tables
tbl_order
id customer_name date
1 Perona 6/7/2018
2 Zorro 6/8/2018
tbl_order_items
id order_id item_name
1 2 compass
2 2 sword
3 2 yakuta
4 1 umbrella
5 1 doll
Expected Results
I want to get all orders and items containing the order.
[
{
id: 1,
customer_name: perona,
data: 6/7/2018,
items: [
{ id: 4, item_name: umbrella },
{ id: 5, item_name: doll },
]
},
{
id: 2,
customer_name: zorro,
data: 6/8/2018,
items: [
{ id: 1, item_name: compass },
{ id: 2, item_name: sword },
{ id: 3, item_name: yakuta },
]
}
]
Is there any option how to do the same in node-mysql?
You can use INNER JOIN to get nested data based on your association.
SELECT [order].*,
[items].[id] AS [items.id]
[items].[item_name] AS [items.item_name]
FROM
(
SELECT [id],
[customer_name],
[date]
FROM [tbl_order]
) AS [order]
INNER JOIN
[tbl_order_items] AS [items]
ON
[order].[id] = [items].[order_id];