I have problem on laravel. I want to showing percentage on with eloquent, but return null value
This Is My Controller
$group_categories = Proyek::with(['modul' => function($query){
$query->select(DB::raw('((select count(*) from modul where status = 0 and deleted_at IS NULL) /
(select count(*) from modul where deleted_at IS NULL)) *
100 as count' ));
}])->get();
This Is Json return
{
id: "10",
proyek: "JuZka",
created_at: "2018-08-12 01:54:04",
updated_at: "2018-09-23 05:49:13",
modul: [ ]
},
You can use code like this:
$all_models = (new Proyek)->count();
$models = (new Proyek)->where('status', 0)->count();
$percentage = $models / $all_models * 100;
$group_categories = Proyek::wheere('modul', $percentage);
Related
I have two tables a coupons table and a coupon_city_map table.
id
coupon_code
1
OFFER20
2
OFFER10
3
OFFER50
4
OFFER40
5
OFFER90
coupon_Id
city_id
1
2
2
3
3
4
4
2
I need coupons with ids 1 4, and 5 for city_id = 2.
So It should fetch all the coupons where city_id=2 i.e. coupons with id 1 and 4
and it should also fetch coupons which don't have key in coupon_city_map i.e 5.
This is what I have tried but the query in [Op.or] is not working, and it returns all the coupons instead.
let coupons = await Coupon.findAll({
where: {
[Op.or]: [
{ '$CouponCities.city_id$': city_id },
{ '$CouponCities.coupon_id$': null },
],
...filters // other filter like is_active: true
},
include: {
model: CouponCity,
attributes: [],
},
attributes: ['id', 'coupon_code', 'discount_per', 'flat_discount', 'discount_upto', 'description', 'display'],
});
The query being generated
SELECT `Coupon`.`id`,
`Coupon`.`coupon_code`,
`Coupon`.`discount_per`,
`Coupon`.`flat_discount`,
`Coupon`.`discount_upto`,
`Coupon`.`description`,
`Coupon`.`display`
FROM `coupons` AS `Coupon`
LEFT OUTER JOIN `coupon_city_map` AS `CouponCities` ON `Coupon`.`id` = `CouponCities`.`coupon_id`
WHERE (`Coupon`.`user_id` IS NULL OR `Coupon`.`user_id` = 1)
AND `Coupon`.`is_active` = true
AND `Coupon`.`is_external` = false
AND `Coupon`.`start_date` < '2020-12-30 10:33:20'
AND `Coupon`.`expiry_date` > '2020-12-30 10:33:20';
Update
I also tried below, but still it is returning all the coupons.
let coupons = await Coupon.findAll({
// where: {
// ...filters,
// },
include: {
model: CouponCity,
required: false,
where: {
[Op.or]: [
{
zone_id: zoneId,
}, {
coupon_id: null,
},
],
},
attributes: [],
},
attributes: ['id', 'coupon_code', 'discount_per', 'flat_discount','discount_upto', 'description', 'display'],
});
...and it generates below query.
SELECT `Coupon`.`id`,
`Coupon`.`coupon_code`,
`Coupon`.`discount_per`,
`Coupon`.`flat_discount`,
`Coupon`.`discount_upto`,
`Coupon`.`description`,
`Coupon`.`display`
FROM `coupons` AS `Coupon`
LEFT OUTER JOIN `coupon_city_map` AS `CouponCities`
ON `Coupon`.`id` = `CouponCities`.`coupon_id`
AND ( `CouponCities`.`zone_id` = 1
AND `CouponCities`.`coupon_id` IS NULL )
WHERE `Coupon`.`is_active` = true
AND `Coupon`.`is_external` = false;
This is what worked for me, query is mess but it works. I am posting all the codes for better understanding for anyone interested.
Here zone is city.
{
const filters = {
start_date: {
[Op.lt]: new Date(),
},
expiry_date: {
[Op.gt]: new Date(),
},
};
if (userId) {
filters[Op.or] = [{
user_id: null,
}, {
user_id: userId,
}];
filters[Op.and] = {
[Op.or]: [
sequelize.literal('CouponZones.zone_id = 1'),
sequelize.literal('CouponZones.coupon_id IS null')
],
};
} else {
filters.user_id = null;
}
let coupons = await Coupon.findAll({
where: {
...filters,
},
include: {
model: CouponZone,
attributes: [],
},
attributes: ['id', 'coupon_code', 'discount_per', 'flat_discount', 'discount_upto', 'description', 'display'],
});
This is the query it generates.
SELECT `Coupon`.`id`,
`Coupon`.`coupon_code`,
`Coupon`.`discount_per`,
`Coupon`.`flat_discount`,
`Coupon`.`discount_upto`,
`Coupon`.`description`,
`Coupon`.`display`
FROM `coupons` AS `Coupon`
LEFT OUTER JOIN `coupon_zone_map` AS `CouponZones`
ON `Coupon`.`id` = `CouponZones`.`coupon_id`
WHERE ( `Coupon`.`user_id` IS NULL
OR `Coupon`.`user_id` = 1 )
AND ((CouponZones.zone_id = 1 OR CouponZones.coupon_id IS null))
AND `Coupon`.`is_active` = true
AND `Coupon`.`is_external` = false;
Use UNION
You can write query like below
SELECT coupons.*
FROM coupons,
coupon_city_map
WHERE coupons.id = coupon_city_map.coupon_id
AND coupon_city_map.city_id = 2
UNION
SELECT coupons.*
FROM coupons
WHERE coupons.id NOT IN(SELECT coupon_city_map.coupon_id
FROM coupon_city_map)
I have two tables that I need to join and need to get the data that I can use to plot.
Sample data for two tables are:
**table1**
mon_pjt month planned_hours
pjt1 01-10-2019 24
pjt2 01-01-2020 67
pjt3 01-02-2019 12
**table2**
date project hrs_consumed
07-12-2019 pjt1 7
09-09-2019 pjt2 3
12-10-2019 pjt1 4
01-02-2019 pjt3 5
11-10-2019 pjt1 4
Sample Output, where the actual hours are summation of column hrs_consumed in table2. Following is the sample output:
project label planned_hours actual_hours
pjt1 Oct-19 24 8
pjt1 Dec-19 0 7
pjt2 Sep-19 0 3
pjt2 Jan-20 67 0
pjt3 Feb-19 12 5
I have tried the following query but it gives error:
Select Sum(a.hrs_consumed), a.date, a.planned_hours
From (SELECT t1.date, t2.month, t1.project, t1.hrs_consumed, t2.planned_hours
from table1 t1 JOIN
table2 t2
on t2.month = t1.date
UNION
SELECT t1.date, t2.month, t1.mon_pjt, t2.hrs_consumed, t1.planned_hours
from table t1 JOIN
table2 t2
on t1.date != t2.month
)
I have tried another way also extracting two tables separately and in javascript trying to join it and sort it but that was also vain.
In Javascript, you could mimic an SQL like request.
This code takes a pipe and
selects wanted key and formats date into a comparable format,
groups by date,
gets the sum of hrs_consumed for each group,
makes a full join (with an updated data set for comparable keys/columns),
selects wanted keys,
applies a sorting.
const
pipe = (...functions) => input => functions.reduce((acc, fn) => fn(acc), input),
groupBy = key => array => array.reduce((r, o) => {
var fn = typeof key === 'function' ? key : o => o[key],
temp = r.find(([p]) => fn(o) === fn(p));
if (temp) temp.push(o);
else r.push([o]);
return r;
}, []),
sum = key => array => array.reduce((a, b) => ({ ...a, [key]: a[key] + b[key] })),
select = fn => array => array.map(fn),
fullJoin = (b, ...keys) => a => {
const iter = (array, key) => array.forEach(o => {
var k = typeof key === 'function' ? key(o) : o[key];
temp[k] = { ...(temp[k] || {}), ...o };
});
var temp = {};
iter(a, keys[0]);
iter(b, keys[1] || keys[0]);
return Object.values(temp);
},
order = keys => array => array.sort((a, b) => {
var result;
[].concat(keys).some(k => result = a[k] > b[k] || -(a[k] < b[k]));
return result
});
var table1 = [{ mon_pjt: 'pjt1', month: '2019-10', planned_hours: 24 }, { mon_pjt: 'pjt2', month: '2020-01', planned_hours: 67 }, { mon_pjt: 'pjt3', month: '2019-02', planned_hours: 12 }],
table2 = [{ date: '2019-12-07', project: 'pjt1', hrs_consumed: 7 }, { date: '2019-09-09', project: 'pjt2', hrs_consumed: 3 }, { date: '2019-10-12', project: 'pjt1', hrs_consumed: 4 }, { date: '2019-02-01', project: 'pjt3', hrs_consumed: 5 }, { date: '2019-10-11', project: 'pjt1', hrs_consumed: 4 }],
result = pipe(
select(o => ({ ...o, date: o.date.slice(0, 7) })),
groupBy('date'),
select(sum('hrs_consumed')),
fullJoin(
select
(({ mon_pjt: project, month: date, ...o }) => ({ project, date, ...o }))
(table1),
'date'
),
select(({ project, date: label, planned_hours = 0, hrs_consumed = 0 }) => ({ project, label, planned_hours, hrs_consumed })),
order(['project', 'label'])
)(table2);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
SELECT project, label,planned_hours,(planned_hours-hours_consumed) AS actual_hours
FROM(
SELECT t1.mon_pjt AS project,date_format(t1.month,'%M-%Y') AS label,
t1.planned_hours,0 AS hours_consumed
FROM table1 t1
UNION
SELECT t2.project,date_format(t2.date,'%M-%Y') AS label,0 as planned_hours,
sum(t2.hours_consumed) AS hours_consumed
FROM table1 t2
GROUP BY project)t
GROUP BY t.project
ORDER BY project
Is it possible to sorting based on data inside while loop? without using the sql order by.
But also after i select which column, it will sort desc or asc based on data inside not sort by database column and limit it only 10 every page
lookup.php
$draw = $_POST['draw'];
$row = $_POST['start'];
$rowperpage = $_POST['length']; // Rows display per page
$columnIndex = $_POST['order'][0]['column']; // Column index
$columnName = $_POST['columns'][$columnIndex]['data']; // Column name
$columnSortOrder = $_POST['order'][0]['dir']; // asc or desc
$searchValue = $_POST['search']['value']; // Search value
## Custom Field value
$searchByName = $_POST['searchByName'];
$searchByGender = $_POST['searchByGender'];
$sel = $con->query("SELECT * FROM a, b WHERE a.nrek=b.nrek GROUP BY a.name");
$records = $con->num_rows();
$totalRecords = $records;
## Total number of records with filtering
$sel = $con-query("SELECT * FROM a, b WHERE a.nrek=b.nrek AND 1 ".$searchQuery."GROUP BY a.name");
$records = $con->num_rwos();
$totalRecordwithFilter = $records;
$empQuery = $con->query("SELECT * FROM a, b, c WHERE a.nrek=b.nrek AND a.kode=c.kode AND a.kode='3' GROUP BY a.nrek ORDER BY ".$columnName." ".$columnSortOrder." limit ".$row.",".$rowperpage");
while ($row1 = $empquery->fetch_array())
{
$querybalance2 = $con->query("SELECT SUM(b.balance) as balance FROM a JOIN a ON a.nrek= b.nrek WHERE a.kode= '$row1[kode]' AND b.period='$_SESSION[lastperiod]'");
$querybalance2 = $con->query("SELECT SUM(b.balance) as balance FROM a JOIN a ON a.nrek= b.nrek WHERE a.kode= '$row1[kode]' AND b.period='$_SESSION[newperiod]'");
$balance2 = $querybalance2->fetch_array();
$balance1 = $querybalance1->fetch_array();
$data[] = array(
"arek"=>$row1[nrek],
"balance1"=>$balance1,
"balance2"=>$balance2
);
}
$response = array(
"draw" => intval($draw),
"iTotalRecords" => $totalRecords,
"iTotalDisplayRecords" => $totalRecordwithFilter,
"aaData" => $data
);
echo json_encode($response);
Ajax.js
var dataTable = $('#empTable').DataTable
({
'processing': true,
'serverSide': true,
'serverMethod': 'post',
//'searching': false, // Remove default Search Control
'ajax':
{
'url':'lookup.php',
'data': function(data)
{
}
},
'columns':
[
{ data: 'arek' },
{ data: 'balance1', className: 'text-center' },
{ data: 'balance2', className: 'text-center' },
]
});
html.php
<table id="empTable" class="display dataTable">
<thead>
<tr>
<th>Nrek</th>
<th>Balance1</th>
<th>Balance2</th>
</tr>
</thead>
</table>
I want to limit it so the data will load and display faster. If user click on the column, datatable will sort it based on data not column. I tried but "invalid json response", because there isn't "balance2" column in database.
Need help and thank you
I am trying to build a query using query builder with complex nested AND and OR conditions. Here is what I have written so far.
$cond_arr = array();
$cond_arr['VehicleBrandModels.status'] = 1;
$query = $this->VehicleBrandModels->find();
$query->hydrate(false);
$query->select($this->VehicleBrandModels);
$query->where($cond_arr);
$VBM_data = $query->toArray();
This will generate a query like below
SELECT * FROM vehicle_brand_models WHERE status = 1;
I want to generate a query with nested AND & OR conditions like below
SELECT * FROM vehicle_brand_models WHERE status = 1 AND ((overall_rating > 0 AND overall_rating < 2) OR (overall_rating >= 2 AND overall_rating < 4) OR (overall_rating >= 4 AND overall_rating <= 5));
Can anybody help to solve how to achieve this in CAKEPHP 3.0 Query builder?
The simplest solution is the following
$cond_arr = [
'VehicleBrandModels.status' => 1,
'OR' => [
['overall_rating >' => 0, 'overall_rating <' => 2],
['overall_rating >=' => 2, 'overall_rating <' => 4],
['overall_rating >=' => 4, 'overall_rating <=' => 5]
]
];
there is a more 'cake' way and if I'll have time I will post it.
But note that from what I see all your OR conditions overlap and you can simply do
$cond_arr = [
'VehicleBrandModels.status' => 1,
'overall_rating >' => 0,
'overall_rating <=' => 5
];
edit: as primised here's the more cake way using query expressions
$query->where(function($exp, $q) {
$exp = $exp->eq('VehicleBrandModels.status', 1);
$conditions1 = $exp->and_([])
->gt('overall_rating ', 0)
->lte('overall_rating ', 2);
$conditions2 = $exp->and_([])
->gt('overall_rating ', 2)
->lte('overall_rating ', 4);
$conditions3 = $exp->and_([])
->gt('overall_rating ', 4)
->lte('overall_rating ', 5);
$orConditions = $exp->or_([$conditions1, $conditions2, $conditions3]);
$exp->add($orConditions);
return $exp;
});
still some conditions are overlapping
I'm trying to move the following query to Linq-to-sql, is it possible?
select * from (
Select top (#Percent) percent with ties *
from(
Select distinct
LoanNumber as LoanNo
From CHE
Left Join RecordingInfo as Rec
On CHE.LoanNumber = Rec.LoanNo
Where Channel = 'LINX'
and CHE.Doc in ('MTG','MOD')
and Rec.LoanNo is null
and LoanNumber >= '#LoanNo'
) A
order by LoanNo #Order
) B
order by LoanNo
I have not seen anyway to do with ties in linq.
I think something like this will work for you.
public static IQueryable<T> TopPercentWithTies<T, TKey>(this IOrderedQueryable<T> query, Expression<Func<T, TKey>> groupByExpression, double percent)
{
var groupedQuery = query.GroupBy(groupByExpression);
int numberToTake = groupedQuery.Count() * percent / 100;
return groupedQuery.Take(numberToTake).SelectMany(t => t);
}
I only tested it with IEnumerable, so I don't know for sure that it'll work properly with IQueryable. I also sorted the list before calling TopPercentWithTies().
Here's the code I used to test it.
int percent = 50;
var people = new []
{
new { Age = 99, Name = "Adam" },
new { Age = 99, Name = "Andrew" },
new { Age = 89, Name = "Bob" },
new { Age = 50, Name = "Cecil" },
new { Age = 50, Name = "Doug" },
new { Age = 50, Name = "Everett" },
new { Age = 35, Name = "Frank" },
new { Age = 25, Name = "Greg" },
new { Age = 15, Name = "Hank" }
};
var sortedPeople = people.AsQueryable().OrderByDescending(person => person.Age);
var results = sortedPeople.TopPercentWithTies(person => person.Age, percent);
foreach (var person in results)
Console.WriteLine(person);
Hope it helps or at least gets you in the right direction. You may want to tweak the logic for calculating numberToTake.