How to store multiple values on a mysql table - mysql

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` ";
}

Related

Select from json column

There is a task to obtain most ordered products from orders table for given period of time. Table have JSON column called details and ordered products IDs are stored there:
{
products: [
{
id: 1,
quantity: 2,
},
{
id: 6,
quantity: 1
}
]
}
Currently, I'm solving it this way, which kind of inefficient:
Order::whereBetween('created_at', $period)
->get('details->products as details')
->flatMap(fn ($order) => $order->details)
->groupBy('id')
->map(fn ($products) => $products->sum('quantity'));
The result contains pairs, where key - product id, and value total count from orders:
[
1 => 2,
6 => 1,
];
Is it possible to query product id and quantity directly?

how to group data entries with same id into a single entry?

I am a beginner in MySQL as well as Typeorm. So my query returns data with the same ID like:
[
{
id: "1",
name: "john",
place: "San Francisco"
},
{
id: "1",
name: "john",
place: "Mumbai"
}
]
Now I want data where there is an entry with a unique id, let's say:
[
{
id: "1",
name: "john",
place: ["San Francisco", "Mumbai"]
}
]
can someone help me, how do I groupBy to achieve this result?
I doubt that you can get an array, but you could use group_concat.
https://mariadb.com/kb/en/group_concat/
The query would be something like
SELECT `id`, group_concat(`name`), group_concat(`place`) FROM <table_name> GROUP BY `id`
if the name doesn't need to be concatenated
SELECT `id`, `name`, group_concat(`place`) FROM <table_name> GROUP BY `id`
And then in your code you can split that string in array. Either use ',' which I think it's the default separator or use a custom one like '!#$!'
With MySQL you can use GROUP_CONCAT:
SELECT
id, name, GROUP_CONCAT(place)
FROM
<table_name>
GROUP BY
id
With TypeScript you can use Array.prototype.reduce():
const data = [{id: "1",name: "john",place: "San Francisco"},{id: "1",name: "john",place: "Mumbai"}]
const dataHash = data.reduce((a, { id, name, place }) => {
a[id] = a[id] || { id, name, place: [] }
a[id].place.push(place)
return a
}, {})
const result = Object.values(dataHash)
console.log(result)

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.

Select from two tables and create object with data

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.

Storing nested JSON with Cassandra

I am trying to store nested JSON object using composite tables in Cassandra and the nodejs bindings.
Let's say my data looks like this (friends and foes actually have more complex data structures than simple map):
{
id: 001,
name: 'luke',
lastname: 'skywalker',
friends: [
{ id: 002,
name: 'han',
lastname: 'solo' },
{ id: 003,
name: 'obiwan',
lastname: 'kenobi' },
{ id: 004,
name: 'leila',
lastname: 'skywalker' }
],
foes: [
{ id: 005,
name: 'dark',
lastname: 'vador' },
{ id: 006,
name: 'boba',
lastname: 'feet' }
]
}
From what I understood from composite keys (here: https://pkghosh.wordpress.com/2013/07/14/storing-nested-objects-in-cassandra-composite_columns/), I expected to store my data like this:
001 | luke | skywalker | friend:002:han:solo | friend:003:obiwan:kenobi | ... | foe:006:boba:feet
I created my table like this:
CREATE TABLE heroes (
id int,
name text,
lastname text,
friend_id int,
friend_name text,
friend_lastname text,
foe_id int,
foe_name text,
foe_lastname text,
PRIMARY KEY ((id, name, lastname), friend_id, foe_id)
);
And then run for each friends or foes:
client.execute(
'INSERT INTO heros (id, name, lastname, friend_id, friend_name, friend_lastname) VALUES (?, ?, ?, ?, ?)',
[001, 'luke', skywalker', 002, 'han', 'solo'],
function(err) {
//some code
}
)
Now, when runing the query 'SELECT * FROM heroes WHERE id=001' I expected to get only one row with all the friends or foes added as column.
Instead I get as many row as there as friends and foes. On top of this, a row for a friend looks like this:
{ rows:
[ { __columns: [Object],
id: 001,
name: 'luke',
lastname: 'skywalker',
friend_id: 002,
friend_name: 'han',
friend_lastname: 'solo',
foe_id: null,
foe_name: null,
foe_lastname: null } ],
meta:
// some data
}
I would have expected it not to have foe_* field at all.
Am I doing something wrong or is it the way cassandra handles composite items?
The result you are getting is be expected, because you have included friend and foes as part of the primary key. Hero has one to many association with friend and foe. In the blog post of mine that you are referring, I have used only the primary entity attributes as primary key. All the children entity attributes are mapped as dynamic columns.