3 tables in MYSQL
table_product - product_id, product_name
table_variane - variant_id, variant_name
table_product_variants - product_id, variant_id, MRP, SellPrice
I want to create JSON data out of those in Perl for all the products, in this format:
[
{
"ProductID": "1",
"ProductName": "Green Detergent Bar",
"Variants": [
{
"VariantID": "1",
"VariantName": "500GM",
"MRP": "20.00",
"SellPrice": "19.50"
},
{
"VariantID": "2",
"VariantName": "1KG",
"MRP": "40.00",
"SellPrice": "38.00"
}
]
},
{
"ProductID": "2",
"ProductName": "ABCD",
"Variants": [
{
"VariantID": "3",
"VariantName": "1KG",
"MRP": "200.00",
"SellPrice": "190.50"
},
{
"VariantID": "2",
"VariantName": "1KG",
"MRP": "40.00",
"SellPrice": "38.00"
}
]
}
]
This is Perl Code
my $sql_query = ""; //need to fill this.
my $statement = $db_handle->prepare ($sql_query) or die "Couldn't prepare query '$sql_query': $DBI::errstr\n";
$statement->execute() or die "SQL Error: $DBI::errstr\n";
my #loop_data = ();
while (my #data = $statement->fetchrow_array())
{
my %data = //need to fill this too.
push(#loop_data, \%data);
}
my $json_text = to_json(\#loop_data);
print $json_text;
Please help in filling SQL query and while loop.
Its just a blueprint. Any modification in code is also fine.
That you need arrays (not hashes) complicates things a bit.
Option 1
Use two queries, one that finds the products, and one that finds the variants of a product.
my $product_sth = $dbh->prepare("
SELECT product_id,
product_name
FROM table_product
");
my $variant_sth = $dbh->prepare("
SELECT tv.variant_id,
tv.variant_name,
tvp.MRP,
tvp.SellPrice
FROM table_product_variants AS tpv
JOIN table_variant AS tv
ON tpv.variant_id = tv.variant_id
WHERE tpv.product_id = ?
");
my #data;
while (my $product_row = $product_sth->fetchrow_hashref()) {
my #variants;
$variant_sth->execute($product_row->{product_id});
while (my $variant_row = $variant_sth->fetchrow_hashref()) {
push #variants, {
VariantID => $variant_row->{variant_id},
VariantName => $variant_row->{variant_name},
MRP => $variant_row->{MRP},
SellPrice => $variant_row->{SellPrice},
};
}
push #data, {
ProductID => $product_row->{product_id},
ProductName => $product_row->{product_name},
Variants => \#variants,
};
}
my $data_json = to_json(\#data);
Option 2
Use an HoA to group the variants of a product when using a single query.
my $sth = $dbh->prepare("
SELECT tp.product_id,
tp.product_name,
tv.variant_id,
tv.variant_name,
tvp.MRP,
tvp.SellPrice
FROM table_product AS tp
JOIN table_product_variants AS tpv
ON tp.product_id = tpv.product_id
JOIN table_variant AS tv
ON tpv.variant_id = tv.variant_id
");
my %data;
while (my $row = $sth->fetchrow_hashref()) {
my $product_id = $row->{product_id};
my $product = $data{$product_id} ||= {
ProductID => $row->{product_id},
ProductName => $row->{product_name},
Variants => [],
};
push #{ $product->{Variants} }, {
VariantID => $row->{variant_id},
VariantName => $row->{variant_name},
MRP => $row->{MRP},
SellPrice => $row->{SellPrice},
};
}
my $data_json = to_json([ values(%data) ]);
Option 3
Use sorting to group the variants of a product when using a single query.
my $sth = $dbh->prepare("
SELECT tp.product_id,
tp.product_name,
tv.variant_id,
tv.variant_name,
tvp.MRP,
tvp.SellPrice
FROM table_product AS tp
JOIN table_product_variants AS tpv
ON tp.product_id = tpv.product_id
JOIN table_variant AS tv
ON tpv.variant_id = tv.variant_id
ORDER BY tp.product_id
");
my $last_product_id = 0;
my #data;
while (my $row = $sth->fetchrow_hashref()) {
my $product_id = $row->{product_id};
if ($product_id != $last_product_id) {
$last_product_id = $product_id;
push #data, {
ProductID => $row->{product_id},
ProductName => $row->{product_name},
Variants => [],
};
}
push #{ $data[-1]{Variants} }, {
VariantID => $row->{variant_id},
VariantName => $row->{variant_name},
MRP => $row->{MRP},
SellPrice => $row->{SellPrice},
};
}
my $data_json = to_json(\#data);
It's a little extra work than option 2, but it has the smallest client-side memory footprint (if you didn't have to keep everything in memory).
Related
This is what i need to achieve:
{"id":1,
"work":[
{
"name":"Pied Piper3"
},
{
"name":"Pied Piper"
}
],
"awards":[
{
"title":"Digital Compression Pioneer Award"
}
]}
This is what i am getting
{"id":1,
"work":[
{
"name":"Pied Piper3"
},
{
"name":"Pied Piper"
}
],
"awards":[
{
"title":"Digital Compression Pioneer Award"
},
{
"title":"Digital Compression Pioneer Award"
}
]}
My query:
select json_object('id',basics.resume_id,
'work',JSON_ARRAYAGG(json_object('name', work.name)),
'awards', JSON_ARRAYAGG(JSON_OBJECT('title', awards.title))
) from basics
left join work on basics.resume_id = work.resume_id
left join awards on basics.resume_id = awards.resume_id where basics.resume_id = 1
I have added two rows of work for resume_id = 1 but only 1 row of awards for resume_id = 1.But I still get as many number of awards in result as per the number of works for resume_id =1
I have Json Data like this :
$data = '[
{
"OrderId": "1038806370",
"qtty": "1",
"Item": "Strawberry 250 gr",
"SKU": "20091"
},
{
"OrderId": "1038806370",
"qtty": "2",
"Item": "Strawberry 130 gr",
"SKU": "20092"
},
{
"OrderId": "1038806370",
"qtty": "1",
"Item": "Strawberry 130 gr",
"SKU": "20092"
}
]';
and I want to Save in my database MySql using PHP Laravel,...
I Want To save data from json to my table, there are table Order values [orderID,...] and OrderDetail values [orderID, SKU, Qty]
This is my code in controller
$order = json_decode($data, true);
foreach ($order as $ord) {
$check = Order::where('orderid', $ord['OrderId'])->get();
if (count($data) > 0) {
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
} else {
Order::create([
'orderid'=> $ord['OrderId'],
]);
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
}
}
but i dont get what i want, I get QTY of SKU 20091 is 2 but actual json data is 3
I'm not sure why you're counting the $data instead of $check variable. You don't really need the $check variable either though. I'll rewrite your code below.
$order = json_decode($data, true);
foreach ($order as $ord) {
// use EXIST query to check if Order exists or not.
if (Order::where('orderid', $ord['OrderId'])->exists())
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
} else {
Order::create([
'orderid'=> $ord['OrderId'],
]);
OrderDetail::firstOrCreate([
'order_id' => $ord['OrderId'],
'sku_id' => $ord['SKU'],
'qty' => $ord['qtty']
]);
}
}
But your if/else could also be removed by using the firstOrCreate() method.
$orders = json_decode($data, true);
foreach ($orders as $order) {
// Get Order Model with orderid = $order['OrderId'] or create it if it doesn't exist
$model = Order::firstOrCreate([
'orderid'=> $order['OrderId']
]);
// Get OrderDetail with provided SKU, qtty and orderid or create it if it doesn't exist.
OrderDetail::firstOrCreate([
'order_id' => $model->orderid
'sku_id' => $order['SKU'],
'qty' => $order['qtty']
]);
}
You could also do it inline.
$orders = json_decode($data, true);
foreach ($orders as $order) {
OrderDetail::firstOrCreate([
'order_id' => Order::firstOrCreate(['orderid'=> $order['OrderId']])->orderid,
'sku_id' => $order['SKU'],
'qty' => $order['qtty'],
]);
}
Here's an example, in csv form, of my mySQL store when.
trek_id, number, name, value, units, userID, deviceID, lat , lng
--------------------------------------------------------------------------------
88, 4, Hum , 720, PPB , 96, 1, 40.0215268, -105.2177324
88, 4, PM10, 720, PPB , 96, 1, 40.0215268, -105.2177324
88, 6, Pres, 730, PPB , 96, 1, 40.0215299, -105.2177096
88, 6, PM10, 730, PPB , 96, 1, 40.0215299, -105.2177096
So a trek_id has multiple number values, and each number contains multiple measurements. I would love to know how to query this so I could eventually insert into a json object that looks like this:
{
"88":{
"4":{
"lat":"40.0215268",
"lng":"-105.2177324",
"userID":96,
"deviceID":"1",
"measurements":[
["Hum",
"PPB",
720
],
["PM10",
"PPB",
720
]
]
},
"6":{
"lat":"40.0215299",
"lng":"-105.2177096",
"userID":96,
"deviceID":"1",
"measurements":[
["Pres",
"PPB",
730
],
["PM10",
"PPB",
720
]
]
}
}
}
So essentially I need to group on trek_id and then again on number.
Ok, first things first: SQL results are FLAT tables. They don't have sub groups or sub array. So you need to handle all sub-grouping in the display code.
Second: You existing data is already perfect for the DISPLAY code (let's say PHP) to create a multi-dimensional array to transform into JSON.
--- HINT PSEUDO_CODE ---
<?php
// assume $results contains your data AND SORTED BY trek_id, number, name
$cur_trek = null;
$cur_number = null;
$json = array();
foreach ($results as $res) {
if ($cur_trek != $res['trek_id']) {
$cur_trek = $res['trek_id'] ;
$json[$cur_trek] = array();
$cur_number = null;
}
if ($cur_number != $res['number']) {
$cur_number = $res['number'];
$json[$cur_trek][$cur_number] =
array(
'lat' => $res['lat'],
'lng' => $res['lng'],
'userID' => $res['userID'],
'deviceID' => $res['deviceID'],
'measurements' => array();
);
}
$json[$cur_trek][$cur_number]['measurements'][] =
array($res['name'], $res['units'], $res['value']);
}
$json = json_encode($json);
I have an array $areaID :
array(3) {
[0]=> array(1) { ["idarea"]=> int(56) }
[1]=> array(1) { ["idarea"]=> int(67) }
[2]=> array(1) { ["idarea"]=> int(116)}
}
Then, I want to select from MySQL database to get data where $areaID in array. My query:
$data = (new \yii\db\Query())
->select('*')
->from('store')
->join('LEFT JOIN','detail_area','detail_area.idareaV = store.idareas')
->join('LEFT JOIN','detail_user','detail_user.id_area = detail_area.idarea')
->where(['in','detail_area.idarea',$areaID])
->all()
But when running,, i got my $areaID is null. Like this :
SELECT * FROM `store` LEFT JOIN `detail_area` ON detail_area.idareaV = store.idareas LEFT JOIN `detail_user` ON detail_user.id_area = detail_area.idarea WHERE (`detail_area`.`idarea` IN (NULL, NULL, NULL))
Can you help me? Thank you ...
Use
->where([
'detail_area.idarea' => array_values(
\yii\helpers\ArrayHelper::map($areaID, 'idarea', 'idarea')
)
])
I'm making a pretty simple RIGHT JOIN query, but I can't format the output correctly.
Here is the Query:
connection.query({sql : "SELECT users.*, rides.* FROM users RIGHT JOIN rides ON users.id = rides.id_user WHERE users.id = ?", nestTables: '_', values : [id] }, function(err, rows){
console.log(rows);
});
This is the output I have:
[ { users_id: 52,
users_firstname: 'greg', //End first table data
rides_latitude: '50.847454', //Second table data: row 1
rides_longitude: '4.358356',
},
{ users_id: 52,
users_firstname: 'greg', //Exactly the same first table data
rides_latitude: '50.9', //Second table data: row 2
rides_longitude: '4.4',
} ]
And this is the ouput I would like to have:
[ { users_id: 52,
users_firstname: 'greg',
rides : [
{
rides_latitude: '50.847454',
rides_longitude: '4.358356'
},
{
rides_latitude: '50.9',
rides_longitude: '4.4'
}
]
}]
I tried nestTables as you can see,
Wrapped for legibility:
connection.query({
sql : "SELECT \
users.users_id, \
users.users_firstname, \
rides.rides_latitude, \
rides.rides_longitude \
FROM \
users \
RIGHT JOIN rides ON users.id = rides.id_user \
WHERE \
users.id = ?",
nestTables: '_',
values : [id]
}, function (err, rows) {
var result = [], index = {};
if (err) throw err;
rows.forEach(function (row) {
if ( !(row.users_id in index) ) {
index[row.users_id] = {
users_id: row.users_id,
users_firstname: row.users_firstname,
rides: []
};
result.push(index[row.users_id]);
}
index[row.users_id].rides.push({
rides_latitude: row.rides_latitude,
rides_longitude: row.rides_longitude
});
});
console.log(result);
});