Date is broken after UNION - mysql

I am trying to UNION two queries. Here is my code:
public function ledger()
{
$name = Input::get('client');
$invoices = DB::table('invoices')
->where('client',$name)
->selectRaw('`invoiceNumber` as `voucher`,`date`,(`bill` + `ot_bill`) as `amount`');
$cashIns = DB::table('cash_ins')
->where('client',$name)
->select('voucher','date','amount')
->unionAll($invoices)
->get();
return view('cashIn.ledger',compact('cashIns'));
}
But the date is not showing in table. When I check with dd($cashIns) all dates are broken or in a different format. I don't understand what has return in date.
array:3 [▼
0 => {#301 ▼
+"voucher": "JKL02390"
+"date": b"ß\x07\f\x06" //it suppose to be 2015-12-06
+"amount": 23888
}
1 => {#304 ▼
+"voucher": "KL8430" //it suppose to be 2015-10-07
+"date": b"""
ß\x07\n
\x07
"""
+"amount": 98392
}
2 => {#305 ▼
+"voucher": "433"
+"date": b"ß\x07\f\x02" //it suppose to be 2015-12-02
+"amount": 9849
}
]
When I individually dd('invoices') and dd('cashIns') without UNION all dates are well formatted and showing exactly as database.

Related

When using a groupby, how to use a different table's column as group key?

I have a table tariff_groups:
id
name
1
Green tariffs
2
Blue tariffs
3
Red tariffs
and I have a table things_usage_tariffs that define which things use which tariffs of a tariff group:
id
thing_id
tariff_group
description
delta
1
1
1
Nice tariff of the Green group.
0
2
1
1
Even nicer tariff of the Green group.
1
3
1
1
Best green tariff.
2
4
1
2
Cool blue tariff.
3
5
1
3
Amazing red tariff.
4
With this code I get all the tariffs that thing with id 1 has:
$tariffs = DB::table('things_usage_tariffs')
->where(
[
'thing_id' => $id,
]
)
->orderBy('delta', 'asc')
->get()
->groupBy('tariff_group')
;
Which returns:
Illuminate\Support\Collection {#1257 ▼
1 => Illuminate\Support\Collection {#1247 ▼
#items: array:4 [▶]
}
2 => Illuminate\Support\Collection {#1253 ▼
#items: array:1 [▶]
}
3 => Illuminate\Support\Collection {#1246 ▼
#items: array:1 [▶]
}
}
Which is cool, but I would like to know how to change the query that I directly get:
Illuminate\Support\Collection {#1257 ▼
'Green tariffs' => array(4)
'Blue tariffs' => array(1)
'Red tariffs' => array(1)
}
I know I could iterate through the result and replace the numeric keys with their respective tariff group name, but for that I would need to make another statement that gets the names and I feel this could be done with a join. Any ideas?
With eloquent and proper relationships:
Two models:
class TariffGroup extends Model{
public function thingsUsageTariffs(){
return $this->hasMany(ThingsUsageTariff::class, 'tariff_group', 'id');
}
}
class ThingsUsageTariff extends Model{
public function tariffGroup(){
return $this->belongsTo(TariffGroup::class, 'id', 'tariff_group');
}
}
Now in your controller:
$tariffs = TariffGroup::with(['thingsUsageTariffs' => function($query){
return $query->orderBy('delta', 'asc');
}])->get();
should yield something similar to what you want to achieve.
If you want to use tables without models, one approach would be to join the tables then apply group by and keyBy to define keys for the groups:
$tariffs = DB::table('things_usage_tariffs')
->join('tariff_groups', 'tariff_groups.id', '=', 'things_usage_tariffs.tariff_group')
->orderBy('things_usage_tariffs.delta', 'asc')
->get()
->groupBy('tariff_group')
->map(function ($group) {
return $group->keyBy('name');
});
This yield should be closer to the result you want.
Note: Name must be unique since we are assigning it as keys. Also, this code is not tested, but I hope this points you in the right direction.

Why laravel select and group by return same value

I try to select count and group with Laravel query, but they are return same value with different field.
This is my code:
$kategoris = ['NUK', 'Hubkel', 'Sta_kawin'];
foreach ($kategoris as $kategori) {
$raw[] = 'count('.$kategori.') as '.$kategori;
}
$implodeRaw = implode(', ', $raw);
$desas = DB::table('arts')
->select('arts.id', 'KDKEC', 'KDDESA', DB::raw($implodeRaw))
->where(['KDKEC' => $kodeKecamatan])
->groupBy('KDDESA')
->orderBy('KDDESA', 'ASC')
->get();
Result:
results: {
0 => {
'id': 10
'NUK': 6
'Hubkel': 6
'Sta_kawin': 6
}
1 => {
'id': 13
'NUK': 1
'Hubkel': 1
'Sta_kawin': 1
}
}
So, what's wrong with this code? I want the NUK, Hubkel, Sta_kawin return different value because the source data is different.

How to avoid _matchingData and get a specific value instead

In the Orders Table Model I need the category ids of the products associated with the order
Model/Table/OrdersTable.php
public function updateQuantityForInventoryItems(array $orders_items): void
{
$ordersItemsIds = [];
foreach ($orders_items as $orders_item) {
array_push($ordersItemsIds, $orders_item->product_id);
}
$catIds = $this->find('ordersItemsCategories', ['ordersItemsIds' => $ordersItemsIds])->toArray();
dd($catIds);
$InventoriesTable = TableRegistry::getTableLocator()->get('Inventories');
$InventoriesTable->updateQuantityForInventoryItems('orders', $catIds);
}
public function findOrdersItemsCategories(Query $query, array $options): Query
{
$query = $this->OrdersItems->Products
->find()
->select(['Products.id','CategoriesProducts.category_id'])
->matching(
'CategoriesProducts', function (Query $q) use ($options) {
return $q->where([
'CategoriesProducts.product_id IN' => $options['ordersItemsIds'],
]);
});
return $query->hydrate(false);
}
the generated SQL query
SELECT Products.id AS `Products__id`, CategoriesProducts.category_id AS `CategoriesProducts__category_id` FROM products Products INNER JOIN categories_products CategoriesProducts ON (CategoriesProducts.product_id in (4325,3632) AND Products.id = (CategoriesProducts.product_id))
When I print out the array with dd($catIds); , I get an array with _matchingData
array:4 [▼
0 => array:2 [▼
"id" => 3632
"_matchingData" => array:1 [▼
"CategoriesProducts" => array:1 [▼
"category_id" => 10
]
]
]
1 => ...
]
how do i get category_id under id
(i have already checked that thread How to print _matchingData object value in cakephp 3 but still no success)
got it. i need to alias the category_id to prevent nesting
->select(['category_id' => 'CategoriesProducts.category_id'])

Yii2 - Where clause for 1:M relation

I have 2 tables :
Product Option Group
id | opt_name | active_flag
------------------------------
1 | Cook level | 0
Product Option List
id | optgrp_id | list_name | active_flag
------------------------------------------
1 | 1 | 25 | 0
2 | 1 | 50 | 1
3 | 1 | 75 | 0
4 | 1 | 100 | 0
Product Option Group Model
public function getOptList()
{
return $this->hasMany(ProdOptlist::className(),['optgrp_id'=>'id']);
}
Product Option List Model
public function getOptGrp()
{
return $this->hasOne(ProdOptgrp::className(),['id'=>'optgrp_id']);
}
Product Option Group Controller
public function actionUpdate($id)
{
$model = $this->findModel($id);
if($model->load(Yii::$app->request->post()) && $model->validate())
{
...
}
else
return $this->render('update', ['model'=>$model]);
}
protected function findModel($id)
{
if (($model = ProdOptgrp::find()
->joinWith('optList')
->where([ProdOptgrp::tableName().'.id'=>$id,
ProdOptgrp::tableName().'.active_flag'=>0,
ProdOptlist::tableName().'.active_flag'=>0])
->one()) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
Update View
Expected output for print_r($model->optList) :
{
[id] => 1
[optgrp_id] => 1
[list_name] => 25
[active_flag] => 0
},
{
[id] => 3
[optgrp_id] => 1
[list_name] => 75
[active_flag] => 0
},
{
[id] => 4
[optgrp_id] => 1
[optList_name] => 100
[active_flag] => 0
}
Actual output :
{
[id] => 1
[optgrp_id] => 1
[list_name] => 25
[active_flag] => 0
},
{
[id] => 2
[optgrp_id] => 1
[list_name] => 50
[active_flag] => 1
},
{
[id] => 3
[optgrp_id] => 1
[list_name] => 75
[active_flag] => 0
},
{
[id] => 4
[optgrp_id] => 1
[optList_name] => 100
[active_flag] => 0
}
Yii2 debugger showing correct query but output still consist of all 4 elements.
Kindly advice if there is any mistake, thank you in advance :)
Even if you use the joinWith() the where() part of your $model = ProdOptgrp::find()... code only limits the result that is returned by the query executed by one() method call. It doesn't affect what is loaded for relations.
If you want to limit what is loaded for relations you can do it:
1) By modifing the existing relation
This is the solution you've come to. You add the where condition directly to the getOptList() method of your ProdOptgrp model. If you do it this way, the $model->optList will always return filtered relation. Depending on case that might be advantage or disadvantage.
2) By adding second relation
You can create another method in your ProdOptgrp model that will define the filtered relation while keeping the original getOptList() unfiltered.
For example like this:
class ProdOptgrp extends \yii\db\ActiveRecord
{
public function getOptList()
{
return $this->hasMany(ProdOptlist::className(),['optgrp_id'=>'id']);
}
public function getFilteredOptList()
{
return $this->getOptList()->where([
ProdOptlist::tableName() . '.active_flag' => 0
]);
}
}
In this case the $model->optList will still contain unfiltered OptLists and the $model->filteredOptList will contain filtered. This solution is good when you need to use both at different spots of your application.
3) By using callback syntax in joinWith() or with()
In case you want to filter the relation only in one particular case you don't need to modify your model. You can modify the relation with callback that is called before loading the data.
$model = ProdOptgrp::find()
->joinWith([
'optList' => function(\yii\db\ActiveQuery $query) {
$query->where([
ProdOptlist::tableName() . '.active_flag' => 0
]);
}
])->where([
ProdOptgrp::tableName().'.id'=>$id,
ProdOptgrp::tableName().'.active_flag'=>0,
ProdOptlist::tableName() . '.active_flag'=>0,
])->one();
The last condition in where() will cause the $model to be null when the active_flag is 0 in optgrp table but 1 in all related records in optlist table. I'm not sure if that is inteded behavior.
You can do it this way too:
//Controller
protected function findModel($id)
{
if (($model = ProdOptgrp::findOne($id)) !== null && $model->isActive()) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
//Model
/*
*Check if model is active
*/
public function isActive(){
return ($this->active_flag == 0) ? true: false;
}
public function getOptList()
{
return $this->hasMany(ProdOptlist::className(),['optgrp_id'=>'id'])->where([ProdOptgrp::tableName().'.active_flag'=>0]);
}
//View
foreach($model->optList as optItem): // you get filtered result

Joining table data

I have a table of:
id title type expl bubble_content onfocus req dorder label mirror
1 Fullname 1 1 Your fullname Yes 0 0 0 NULL
Then another table of:
id fieldid relid dorder
4 1 2 0
5 1 1 0
How would I join the two tables so that the result would be something like:
0 => array(
'id' => 1,
'title' => 'Fullname',
.... etc ....
'relid' => 2,
'relid' => 1),
1 => array(
.... etc ....
))
I've tried using INNER JOIN / LEFT JOIN but this produces two rows/arrays for each relid, I would really like all the data for the particular fieldid to exist within the same array, as illustrated above.
You can't have 2 keys with the same name in an array. On your example you have 2 'relid', the second one will overwrite the first.
You can code PHP so that it merges those rows into one:
$output = array();
while ($row = mysql_fetch_assoc($result))
{
// Capture all values for this row first.
// If this is the new row from the first table, store.
if (!isset($output[$row['id']]))
{
$output[$row['id']] = $row;
// Make a new array for relids.
$output[$row['id']]['relids'] = array();
}
$output[$row['id']]['relids'][] = $row['relid'];
}
Your output array will look like this:
0 => array(
'id' => 1,
'title' => 'Fullname',
.... etc ....
'relids' => array(2, 1),
1 => array(
.... etc ....
))