get data from intermediate table in laravel - laravel-7

i have 2 model(SaleInvoice and Product) with many to many relation
in SaleInvoice model :
public function products()
{
return $this->belongsToMany(Product::class, 'sale_invoice_product', 'saleInvoice_id', 'product_id')->withPivot('count');
}
in Product Model:
public function saleInvoices()
{
return $this->belongsToMany(SaleInvoice::class, 'sale_invoice_product', 'product_id', 'saleInvoice_id');
}
this is the example of data that recorded in sale_invoice_product table(intermediate table)
id | saleInvoiceId | product_id | count
1 | 1500 | 1 | 3
2 | 1500 | 3 | 2
3 | 1500 | 4 | 4
4 | 1501 | 1 | 1
5 | 1501 | 4 | 1
how can i access to data of product and sale invoice from this table like below(in json mode for api request)
product_id | product_name | count | saleInvoice | date
1 LG 3 1500 2020-05-12
3 SONY 2 1500 2020-05-13
4 OT 4 1500 2020-05-17
1 LG 1 1501 2020-05-19
4 OT 1 1501 2020-05-22
i want to return a json file in SaleInvoiceController with top format

Your work was good, Just enough make a API resource for this model and send attributes as you want, For accessing to pivot table you could use $product->pivot->count.

You can try one of these methods
Building a model for sale_invoice_product table with relations to SaleInvoice and Product. Then manually construct the JSON in your controller
Build an SQL View and a Model for it
Solution 1: Building a model to the intermediate table and manually constructing the JSON
Let's say you built a model called SaleInvoiceProduct that has product() relation to the Products table and saleInvoice() relation to the SaleInvoices table. In your controller you can do this
$resultInvoiceProducts = [];
$allSaleInvoiceProducts = SaleInvoiceProduct::all();
foreach ($allSaleInvoiceProducts as oneSaleInvoiceProduct) {
$tempSaleInvoiceProduct = new stdClass();
$tempSaleInvoiceProduct->product_id = oneSaleInvoiceProduct->product_id;
$tempSaleInvoiceProduct->product_name = oneSaleInvoiceProduct->product->name;
$tempSaleInvoiceProduct->saleInvoiceId = oneSaleInvoiceProduct->saleInvoiceId;
$tempSaleInvoiceProduct->data = oneSaleInvoiceProduct->saleInvoice->date;
array_push($resultInvoiceProducts, $tempSaleInvoiceProduct);
}
Solution 2: Using SQL Views
You can create an SQL View that uses Joins to construct the data you need
DROP VIEW IF EXISTS vSaleInvoiceProduct;
CREATE VIEW vSaleInvoiceProduct AS
SELECT sp.product_id,
sp.saleInvoiceId,
sp.`count`,
p.product_name,
s.`date`
FROM SaleInvoiceProduct sp
LEFT JOIN SaleInvoices s on sp.saleInvoiceId = s.saleInvoiceId
LEFT JOIN Products p on sp.product_id = p.product_id
Then you can create a Laravel model for this View just like you would do for any table, call the ::all() method on it and directly return the results with json()

Related

Codeigniter 4 Model Relationship Entity

I have database tables that look like this : Table 1 : transaction
id|buyer_id|transaction_date
----------------------------
1 | 1 |2020-01-01
2 | 4 |2020-03-04
3 | 6 |2020-11-12
----------------------------
Table 2 : transaction_detail
id|transaction_id|item_id|qty
--------------------------------
1| 1 | 1 | 3 |
2| 1 | 4 | 1 |
3| 1 | 6 | 2 |
--------------------------------
transaction_detai.transaction_id is a foreign key to transaction.id
How can I select data in transaction table but also get all the transaction_detail as a child ? If I use join, it will generate all data in one row. I need something just like this :
Array(
[0] => Master\Entities\Transaction Object
(
[id:protected] =>
[buyer_id:protected] =>
[transaction_date:protected] =>
[transaction_detail:protected]=>
Array(
[0] => Master\Entities\TransactionDetail Object
(
[id:protected] =>
[transaction_id:protected] =>
[item_id:protected] =>
[qty:protected] =>
)
)
)
)
Your Context not clear whether you need it be done with model or with query builders. Using builders you can create a multidimensional array and place details accordingly and sample code for that is as:
$db = \Config\Database::connect();
// Fetch all details from main table say `transaction`
$dataMain = $db->table('transaction')
->where('transaction.deleted_at',NULL)
->select('transaction.id,
transaction.buyer_id,transaction.transaction_date')
->get()
->getResult();
$result = [];
foreach($dataMain as $dataRow){
// For each master table row generate two sub array one to store main table row and other to hold details table data respective to main table row
if(!isset($result[$dataRow->id])){
$result[$dataRow->id]['transaction'] = [];
$result[$dataRow->id]['transaction_details'] = [];
array_push($result[$dataRow->id]['transaction'],$dataRow);
}
$dataSecondary = $db->table('transaction_detail')
->where('transaction_detail.deleted_at',NULL)
->select('transaction_detail.id,
transaction_detail.transaction_id,
transaction_detail.item_id,transaction_detail.qty')
->where('transaction_detail.offer_id',$dataRow->id)
->get()
->getResult();
array_push($result[$dataRow->id]['transaction_details'],$dataSecondary);
}
// $result[$id]['transaction'] - contains master table data
// $result[$id]['transaction_details'] - contains sub table datas associated with respective master table data
print '<pre>';
var_dump($result);
exit;

access each group in spark keyvaluegroupeddataset

I am new to Spark and I have a specific question about how to use spark to address my problem, which may be simple.
Promblem:
I have a model, which predicts the sales of products. Each product also belongs to a category like shoes, clothes etc. And we also have actual sales data. So the data look like this:
+------------+----------+-----------------+--------------+
| product_id | category | predicted_sales | actual_sales |
+------------+----------+-----------------+--------------+
| pid1 | shoes | 100.0 | 123 |
| pid2 | hat | 232 | 332 |
| pid3 | hat | 202 | 432 |
+------------+----------+-----------------+--------------+
product_id category predicted_sales actual_sales
What I'd like to do is: I want to calculate the number(or percentage) of intersection between top 5% products ranked by actual_sales and top 5% products ranked by predicted_sales for each category.
Doing this for the whole products instead of for each category would be easy, something like below:
def getIntersectionRatio(df:dataframe, per :Int): Double = {
val limit_num = (df.count() * per / 100.0).toInt
var intersection = df.orderBy("actual_sales").limit(limit_num)
.join(df.orderBy("predicted_sales").limit(limit_num), Seq("product_id"), "inner")
intersection.count() * 100.0 / limit_num
}
However, I need to calculate the intersection for each category. The result will be something like this
+-----------+------------------------+
| Category | intersection_percentage|
+-----------+------------------------+
My ideas
User Defined Aggreation Fuction or Aggregators
I think I can achieve my goal if I use groupBy or GroupByKey with UDAF or Aggregators but they are too inefficient because they take 1 row each time and I will have to store each row in the buffer inside UDAF or Aggregator.
df.groupby("category").agg(myUdaf)
class myUdaf extends UserDefinedAggregateFunction {
//Save all the rows to an arraybuffer
//and then transform the buffer back to df
//And then we the the same thing as we did for whole product in getIntersectionRatio defined previously
}
Self implemented partitioning
I can select the distinct categories and the use map to process each category, in which I join the element with df to get the partition
df.select("category").distinct.map(myfun(df))
def myfun(df: dataframe)(row : Row):Row = {
val dfRow = row.toDF //not supported but feasible with other apis
val group = df.join(broadcast(dfRow), seq(category), inner)
getIntersectionRatio(group)
}
Do we have a better solution for this?
Thanks in advance!

COGNOS Report: COUNT IF

I am not sure how to go about creating a custom field to count instances given a condition.
I have a field, ID, that exists in two formats:
A#####
B#####
I would like to create two columns (one for A and one for B) and count instances by month. Something like COUNTIF ID STARTS WITH A for the first column resulting in something like below. Right now I can only create a table with the total count.
+-------+------+------+
| Month | ID A | ID B |
+-------+------+------+
| Jan | 100 | 10 |
+-------+------+------+
| Feb | 130 | 13 |
+-------+------+------+
| Mar | 90 | 12 |
+-------+------+------+
Define ID A as...
CASE
WHEN ID LIKE 'A%' THEN 1
ELSE 0
END
...and set the Default aggregation property to Total.
Do the same for ID B.
Apologies if I misunderstood the requirement, but you maybe able to spin the list into crosstab using the section off the toolbar, your measure value would be count(ID).
Try this
Query 1 to count A , filtering by substring(ID,1,1) = 'A'
Query 2 to count B , filtering by substring(ID,1,1) = 'B'
Join Query 1 and Query 2 by Year/Month
List by Month with Count A and Count B

How to cycle a Pandas dataframe grouping by hierarchical multiindex from top to bottom and store results

I'm trying to create a forecasting process using hierarchical time series. My problem is that I can't find a way to create a for loop that hierarchically extracts daily time series from a pandas dataframe grouping the sum of quantities by date. The resulting daily time series should be passed to a function inside the loop, and the results stored in some other object.
Dataset
The initial dataset is a table that represents the daily sales data of 3 hierarchical levels: city, shop, product. The initial table has this structure:
+============+============+============+============+==========+
| Id_Level_1 | Id_Level_2 | Id_Level_3 | Date | Quantity |
+============+============+============+============+==========+
| Rome | Shop1 | Prod1 | 01/01/2015 | 50 |
+------------+------------+------------+------------+----------+
| Rome | Shop1 | Prod1 | 02/01/2015 | 25 |
+------------+------------+------------+------------+----------+
| Rome | Shop1 | Prod1 | 03/01/2015 | 73 |
+------------+------------+------------+------------+----------+
| Rome | Shop1 | Prod1 | 04/01/2015 | 62 |
+------------+------------+------------+------------+----------+
| ... | ... | ... | ... | ... |
+------------+------------+------------+------------+----------+
| Milan | Shop3 | Prod9 | 31/12/2018 | 185 |
+------------+------------+------------+------------+----------+
| Milan | Shop3 | Prod9 | 31/12/2018 | 147 |
+------------+------------+------------+------------+----------+
| Milan | Shop3 | Prod9 | 31/12/2018 | 206 |
+------------+------------+------------+------------+----------+
Each City (Id_Level_1) has many Shops (Id_Level_2), and each one has some Products (Id_Level_3). Each shop has a different mix of products (maybe shop1 and shop3 have product7, which is not available in other shops). All data are daily and the measure of interest is the quantity.
Hierarchical Index (MultiIndex)
I need to create a tree structure (hierarchical structure) to extract a time series for each "node" of the structure. I call a "node" a cobination of the hierarchical keys, i.e. "Rome" and "Milan" are nodes of Level 1, while "Rome|Shop1" and "Milan|Shop9" are nodes of level 2. In particulare, I need this on level 3, because each product (Id_Level_3) has different sales in each shop of each city. Here is the strict hierarchy.
Nodes of level 3 are "Rome, Shop1, Prod1", "Rome, Shop1, Prod2", "Rome, Shop2, Prod1", and so on. The key of the nodes is logically the concatenation of the ids.
For each node, the time series is composed by two columns: Date and Quantity.
# MultiIndex dataframe
Liv_Labels = ['Id_Level_1', 'Id_Level_2', 'Id_Level_3', 'Date']
df.set_index(Liv_Labels, drop=False, inplace=True)
The I need to extract the aggregated time series in order but keeping the hierarchical nodes.
Level 0:
Level_0 = df.groupby(level=['Data'])['Qta'].sum()
Level 1:
# Node Level 1 "Rome"
Level_1['Rome'] = df.loc[idx[['Rome'],:,:]].groupby(level=['Data']).sum()
# Node Level 1 "Milan"
Level_1['Milan'] = df.loc[idx[['Milan'],:,:]].groupby(level=['Data']).sum()
Level 2:
# Node Level 2 "Rome, Shop1"
Level_2['Rome',] = df.loc[idx[['Rome'],['Shop1'],:]].groupby(level=['Data']).sum()
... repeat for each level 2 node ...
# Node Level 2 "Milan, Shop9"
Level_2['Milan'] = df.loc[idx[['Milan'],['Shop9'],:]].groupby(level=['Data']).sum()
Attempts
I already tried creating dictionaries and multiindex, but my problem is that I can't get a proper "node" use inside the loop. I can't even extract the unique level nodes keys, so I can't collect a specific node time series.
# Get level labels
Level_Labels = ['Id_Liv'+str(n) for n in range(1, Liv_Num+1)]+['Data']
# Initialize dictionary
TimeSeries = {}
# Get Level 0 time series
TimeSeries["Level_0"] = df.groupby(level=['Data'])['Qta'].sum()
# Get othe levels time series from 1 to Level_Num
for i in range(1, Liv_Num+1):
TimeSeries["Level_"+str(i)] = df.groupby(level=Level_Labels[0:i]+['Data'])['Qta'].sum()
Desired result
I would like a loop the cycles my dataset with these actions:
Creates a structure of all the unique node keys
Extracts the node time series grouped by Date and Quantity
Store the time series in a structure for later use
Thanks in advance for any suggestion! Best regards.
FR
I'm currently working on a switch dataset that I polled from an sql database where each port on the respective switch has a data frame which has a time series. So to access this time series information for each specific port I represented the switches by their IP addresses and the various number of ports on the switch, and to make sure I don't re-query what I already queried before I used the .unique() method to get unique queries of each.
I set my index to be the IP and Port indices and accessed the port information like so:
def yield_df(df):
for ip in df.index.get_level_values('ip').unique():
for port in df.loc[ip].index.get_level_values('port').unique():
yield df.loc[ip].loc[port]
Then I cycled the port data frames with a for loop like so:
for port_df in yield_df(adb_df):
I'm sure there are faster ways to carry out these procedures in pandas but I hope this helps you start solving your problem

Cassandra how to add values in a single row on every hit

In this table application will feed us with the below data and it will be incremental as and when we will receive updates on the status . So initially table will look like the below as shown:-
+---------------+---------------+---------------+---------------+
| ID | Total count | Failed count | Success count |
+---------------+---------------+---------------+---------------+
| 1 | 30 | 10 | 20 |
+---------------+---------------+---------------+---------------+
Now let’s assume total 30 messages are pushed now out of which 10 Failed and 20 Success as shown above.Now again application is run and values changed . Now total 20 new records came in out of which all are success. This should be updated in the same row .
+---------------+---------------+---------------+---------------+
| ID | Total count | Failed count | Success count |
+---------------+---------------+---------------+---------------+
| 1 | 50 | 10 | 40 |
+---------------+---------------+---------------+---------------+
Is it feasible in Cassandra DB using Counter data type?
Of course you can use counter tables in your case.
Let's assume table structure like :
CREATE KEYSPACE Test WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 3 };
CREATE TABLE data (
id int,
data string,
PRIMARY KEY (id)
);
CREATE TABLE counters (
id int,
total_count counter,
failed_count counter,
success_coutn counter,
PRIMARY KEY (id)
);
You can increment counters by running queries like :
UPDATE counters
SET total_count = total_count + 1,
success_count = success_count + 1
WHERE id= 1;
Hope this can help you.

Resources