I'm using yajra's laravel/datatables plugin and I want to send only the first row of every group from the query sorted according to date of the record descending. This is my query :
$qsrecords = QualityScore::where('clientID', '=', $user['id'])
->whereBetween('day', array($startDate, $endDate))
->where($desiredValue, $operator, $quantity)
->where('previousQualityScore','!=','0');
This query returns every record for this given user id like :
Client ID | Keyword ID | Quality Score | Date
2 81 8 21.08.2016
2 42 9 19.08.2016
2 81 7 16.08.2016
2 42 5 14.08.2016
as you can see, ı got 2 different keywords and my query is giving that output.
but i want my query to generate results like :
Client ID | Keyword ID | Quality Score | Date
2 81 8 21.08.2016
2 42 9 19.08.2016
Only the last records of every keyword. That's I want to achieve.
The way i send the query to view :
// Send data to view via datatables plugin
return Datatables::of($qsrecords)->make(true);
Try this
QualityScore::select( * , DB::raw('MAX(date) as date'))
->where('clientID', '=', $user['id'])
->whereBetween('day', array($startDate, $endDate))
->where($desiredValue, $operator, $quantity)
->where('previousQualityScore','!=','0');
->groupBy('keyword_id')
->get();
Finally i've figured it out! I've changed the way i approach to this issue but the following code has solved the issue, thanks #Kiran-sadvilkar for suggestions.
$groupByMaxDateQuery = ' SELECT qs.adGroup,qs.keyword, qs.previousQualityScore, qs.qualityScore, qs.qualityScoreDifference, qs.day
FROM homestead.qualityScore AS qs
INNER JOIN (
SELECT adGroupID, keywordID, max(day)
AS MaxDay
FROM homestead.qualityScore
GROUP BY adGroupID,keywordID
)
innerTable ON qs.adGroupID = innerTable.adGroupID
AND qs.keywordID = innerTable.keywordID
AND qs.day = innerTable.MaxDay
WHERE qs.clientID = '.$user['id'].' AND
qs.day BETWEEN "'.$startDate.'" AND "'.$endDate.'" AND
qs.'.$desiredValue.' '.$operator.' '.$quantity.' AND
qs.previousQualityScore != 0
';
// Pull data from database with current conditions
$qsrecords = DB::table(DB::raw("($groupByMaxDateQuery) as qs"));
As a result i've decided to use a raw sql query and now it works...
Related
Let's say we have two tables:
Payments
id
reason_id
amount
1
1
100
2
2
10
3
1
30
Payment Reasons
id
title
is_discount
1
Payment for something
0
2
Discount for something
1
I'd like to query payments table and sum amount column based on its relationship payment_reasons.is_discount value:
total_received
total_discounted
130
10
How to achieve this?
If you want to get the data in one db-request, I don't think there is a clean laravel-way to solve this. I've been trying out some raw mysql to get it into a working query and it would look like this:
select
sum(if(pr.is_discount = 0, p.amount, 0)) as total_received,
sum(if(pr.is_discount = 1, p.amount, 0)) as total_discounted
from payments p
join payment_reasons pr on pr.id = p.reason_id
The if statement will render if discount needs to be used per row and the sum wil simply sum all the end-results together.
Doing this in laravel with a model does not really make sence, since there are no fields in the result which your model could use anyway. In this case, using eloquent would be more (unmaintainable) code than a simple Query Builder:
$data = DB::select('
select
sum(if(pr.is_discount = 0, p.amount, 0)) as total_received,
sum(if(pr.is_discount = 1, p.amount, 0)) as total_discounted
from payments p
join payment_reasons pr on pr.id = p.reason_id
')
If you don't mind doing multiple queries to fetch the data, models make more sense:
$totalReceived = Payment
::whereHas('paymentReason', fn($q) => $q->where('is_discount', 0))
->sum('amount');
$totalDiscounted = Payment
::whereHas('paymentReason', fn($q) => $q->where('is_discount', 1))
->sum('amount');
Please note that this example will perform 4 queries, 2 on payments, and 2 on payment_reasons
I use Laravel 6.12, I have this request :
$queryJob = DB::table('jobs as j')->join('job_translations as jt', 'j.id', 'jt.job_id')
->whereNull('j.deleted_at')
->whereNull('jt.deleted_at')
->select('j.id', 'j.short_name', 'j.status', DB::raw("case when j.short_name = '{$request->short_name}' then 0 else 1 end"))
->distinct();
$jobs = $queryJob->paginate($qtyItemsPerPage);
The results displays an error for the total :
The total = 3, but as you can see the data contains only 2 elements.
I read here that when using a distinct, I must be clear on which column the total must be calculated: distinct() with pagination() in laravel 5.2 not working
So I modified my query like that:
$jobs = $queryJob->paginate($qtyItemsPerPage, ['j.*']);
But without success, the total is still wrong.
Hoping that I don't misunderstand your DB and relations structure and purpose of your query perhaps this will avoid using distinct or groupBy altogether?
$shortname = $request->input('short_name');
$queryJob = Job::with('job_translations')->select('id','short_name',
'status', DB::raw("case when short_name = '" . $shortname . "'
then 0 else 1 end")
->paginate($qtyItemsPerPage);
Pagination can be easily manually added with skip and take in case you need to use groupBy
$queryJob->skip(($page - 1) * $qtyItemsPerPage)->take($qtyItemsPerPage)->get();
The solution for me was to pass a field name to the distinct() method.
With your example:
$queryJob = DB::table('jobs as j')
// joins, where and other chained methods go here
->distinct('j.id')
Solution taken from https://stackoverflow.com/a/69073801/3503615
I am using PigLatin. And I want to remove the duplicates from the bags and want to retain the last element of the particular key.
Input:
User1 7 LA
User1 8 NYC
User1 9 NYC
User2 3 NYC
User2 4 DC
Output:
User1 9 NYC
User2 4 DC
Here the first filed is a key. And I want the last record of that particular key to be retained in the output.
I know how to retain the first element. It is as below. But not able to retain the last element.
inpt = load '......' ......;
user_grp = GROUP inpt BY $0;
filtered = FOREACH user_grp {
top_rec = LIMIT inpt 1;
GENERATE FLATTEN(top_rec);
};
Can anybody help me on this? Thanks in advance!
#Anil : If you order by one of the fields in descending order. You will be able to get the last record. In the below code, have ordered by second field of input (field name : no in script)
Input :
User1,7,LA
User1,8,NYC
User1,9,NYC
User2,3,NYC
User2,4,DC
Pig snippet :
user_details = LOAD 'user_details.csv' USING PigStorage(',') AS (user_name:chararray,no:long,city:chararray);
user_details_grp_user = GROUP user_details BY user_name;
required_user_details = FOREACH user_details_grp_user {
user_details_sorted_by_no = ORDER user_details BY no DESC;
top_record = LIMIT user_details_sorted_by_no 1;
GENERATE FLATTEN(top_record);
}
Output : DUMP required_user_details
(User1,9,NYC )
(User2,4,DC)
Ok.. You can use RANK Operator .
Hope the below code helps.
rec = LOAD '/user/cloudera/inputfiles/sample.txt' USING PigStorage(',') AS(user:chararray,no:int,loc:chararray);
rec_rank = rank rec;
rec_rank_each = FOREACH rec_rank GENERATE $0 as rank_key, user, no, loc;
rec_rank_grp = GROUP rec_rank_each by user;
rec_rank_max = FOREACH rec_rank_grp GENERATE group as temp_user, MAX(rec_rank_each.rank_key) as max_rank;
rec_join = JOIN rec_rank_each BY (user,rank_key) , rec_rank_min BY(temp_user,max_rank);
rec_output = FOREACH rec_join GENERATE user,no,loc;
dump rec_output;
Ensure that you run this from pig 0.11 version as rank operator introduced from pig 0.11
I am try to add id from one table to another table to give a relationship to the tables.
i have 2 table ..
classes.(id,cls,divn)
id cls divn
1 1 A
2 1 B
4 2 A
5 2 B
6 2 C
7 3 A
2.teacher(id teachername,tclsid,tsub)
Now i want ,im enter teachername and select class,division ,subject on select box using html tag.
if im select class and division check to classes table.and get id from selected class & division to insert into teacher table tclsid feld.
how its possible??
im trying to select multiple class and division
im using controller.php is here
$clss =implode(',', Input::get('tcls'));
$divn =implode(',', Input::get('tdivn'));
$teachers =new ForumTeacher();
$teachers ->tname=Input::get('tname');
$teachers->tmobile=Input::get('tmobile');
$teachers ->ttype=Input::get('ttype');
$teachers ->tsubject = implode(',', Input::get('tsubject'));
$cs = ForumClass::where('cls', $clss)->where('divn', $divn )->first();
$teachers->tcls= $cs->id;
but not work this code $teachers->tcls= $cs->id;` ...
i want teacher table like this
id teachername tclsid tsub
1 xyz 1,5 maths
2 poq 5,7 english
if xyz teacher select class &division are 1,2 & A,B(so id is 1,5)
if poq teacher select class &division are 2,3 & B,A (so id is 5,7)
but i got an error
ErrorException (E_UNKNOWN)
Trying to get property of non-object
error code line is
$teachers->tcls= $cs->id;
Your $teachers var is holding a new, unsaved ForumTeacher model. You have not assigned the tcls value in $teachers. So the $teachers['tcls'] is not set, Add:
$teachers->tcls = $cs->id;
I don't understand what your are trying to do with:
$clsid[$cs->id] = $teachers['tcls'];
If you set the tcls attribute of $teachers first, what you are doing is the same as:
$clsid[$cs->id] = $cs->id;
Don't forget to save the model when you are done setting its attributes:
$teachers->save();
Get id from one table an add another table in laravel 4
$cs = ForumClass::where('cls','=', $clss)->where('divn','=', $divn )->first();
$teachers->tcls= $cs->id;
Reread your question and code and from what I understand you are getting multiple class, division combinations and subject for multiple teachers. You either have to have one teacher and one cls and one divn and one subject or the same number of these corresponding to different teachers. Otherwise, I am confused by your model, so I am assuming you have one of each per teacher instance.
Then you need to iterate over the inputs and create one teacher at a time or create an array and batch create them. I'll do the iteration for simplicity of following it:
// assuming all input arrays have the same count() of elements and
// are all in the same order
$tclss = Input::get('tcls');
$tdivns = Input::get('tdivn');
$tnames = Input::get('tname');
$tmobiles = Input::get('tmobile');
$ttypes = Input::get('ttype');
$tsubjects = Input::get('tsubject');
$iMax = count($tclss);
for ($i = 0; $i < $iMax; $i++)
{
$tcls = ForumClass::where('cls', $tclss[$i])->where('divn', $tdivns[$i])->get();
if (is_null($tcls))
{
// cls, divn combination is missing from your table
// if you want to add it then do so or handle the error
$tcls = new ForumClass();
$tcls->cls = $tclss[$i];
$tcls->divn = $divns[$i];
$tcls->Save();
}
$teacher = new ForumTeacher();
$teacher->tname = $tnames[$i];
$teacher->tmobile = $tmobiles[$i];
$teacher->ttype = $ttypes[$i];
$teacher->tsubject = $tsubjects[$i];
$teacher->tcls = $tcls->id;
$teacher->save();
}
I did not test this but you get the idea of what to do.
I search lot but not getting any help on random records with mysql.I am using random query to get random data from database with not in with some limit. If database contains 100 records and suppose I am giving 30 as limit with random function and some not in id.My problem is that when it hit first time I am giving not in id as empty and it is giving me 30 records randomly.But for second time except last 30 records i.e(it is in not in variable) it should give me another 30 records from 70 records but it is giving me less than 30 i.e(28,29).This because first it applies random function and limit and then filter it with not in.My query is like below:
$subQuery = $this->select()
->from(array('s' => 'shop'), array('s.shop_id','b.shop_name','b.shop_template_id'))
->order('RAND()')
->where('s.shop_id NOT in (?)', $shop_id)
->limit(30);
$query = $this->select()
->from(array('b' => $subQuery), array('*'))
->join(array('p' => 'product'), 's.shop_id = p.shop_id', array('p.product_price'))
->setIntegrityCheck(false);
$resultRows = $this->fetchAll($query);
Update: I got the problem why it is giving (28,29) records sometime because join query contains product for shop and if some shop is having 0 products it does not get that shop.My question is that irrespective of product how can i get that shop from database.
Your problem is that you join instead of left join. Also there's no need for a sub select. This should work:
$objSelect = $this->select()->setIntegrityCheck(false);
$objSelect->from(
array('s' => 'shop'),
array('s.shop_id','b.shop_name','b.shop_template_id')
);
$objSelect->joinLeft(
array('p' => 'product'),
's.shop_id = p.shop_id',
array('p.product_price')
);
$objSelect->order('RAND()');
$objSelect->limit(30);
$objRowSet = $this->fetchAll($objSelect);