Laravel SQL Group by and join to select name - laravel

I have a table classed Test which has columns EmployerID and an Employers table with it's index EmployerID.
I need to group Test entries by EmployerID, join the employers table and also pull the employer name but I'm prevented from doing so because the sql error that says that the column is not in any aggregate function or group by clause.
$test = $this->Test()
->selectRaw("SUM(Amount) AS Amount, AVG(Rate) AS Rate, Month, Employers.Name AS 'EmployerName'")
->join('Employers', 'Employers.EmployerID', '=', 'Test.EmployerID')
->groupBy(['Month', 'Test.EmployerID']);

Related

How to solve Laravel union queries with different number of columns

I have two tables contact_us and upload_new_car.
contact_us table contains columns:
id
name
email
phone
message
created_at
updated_at
upload_new_car contains columns:
id
name
phone_number
car_name
car_price
location
car_model_year
car_model
variant
driven
fuel
transmission
city
no_of_owners
upload_1
upload_2
upload_3
upload_4
upload_5
created_at
updated_at
How can I get the UNION of these tables in Laravel? Please help
Not allowing to different size of columns is not laravel's businuess. It is a matter of SQL .You can follow [this link] for more info about UNION statements .
On the other hand for laravel you can use those syntax using union (We can benefit from selecting the same count of columns from each tables).
$first = DB::table('contact_us')
->select('name','phone');
$users = DB::table('users')
->select('name','phone_number as phone')
->union($first)
->get();
dd($users)

row count from second table with more than one table join

I have three table:
TABLE1:
jobposts (id,user_id,qualification_id)
TABLE2:
appliedjobs (id,jobposts_id,message)
TABLE3:
qulificationmasters (id, qualificationame)
jobposts_id from TABLE is foreign key of id of jobposts
I need all records from jobposts with row count of appliedjobs
I tried by this:
$jobposteddetails = DB::table('jobposts')
->rightJoin('qulificationmasters','qulificationmasters.id', '=', 'jobposts.qualification_id')
->leftJoin('appliedjobs','appliedjobs.jobposts_id', '=', 'jobposts.id')
->select('jobposts.*','qulificationmasters.QualificationName', DB::raw('count(appliedjobs.id) as counts'))
->where('jobposts.user_id', '=', $user->id)
->groupBy('appliedjobs.id')
->get();
But gives error like: it wants every column in groupby of jobposts and qulificationmasters and qulificationmasters.id
But gives error like: it wants every column in groupby of jobposts and qulificationmasters and qulificationmasters.id
If I groupby with all columns of jobposts and qulificationmasters then it is working good.
But why all the columns gropuby.
Go in config folder database.php find mysql array and make strict to false and check again.

LINQ Join and performing aggregate functions

I am facing issue in writing LINQ query to perform join on three tables and then performing aggregate functions on the rows. Kindly do provide some help.
I have three tables
Table 1: Students (Id, Name)
Table 2: Subject (SubID, Title, Id)
Table 3: Grade (Id, SubID, marks)
I have to write LINQ query to get the results as following
Count of Students table rows
Count of Grade table rows
Sum of
marks of all rows in Grade table
I am writing query as following but it is not up to the mark as i feel it is not correct.
var _Count = from student in _context.Students
join subject in _context.Subject on student.Id equals subject.Id
join grade in _context.Grade on subject.SubID equals grade.SubID
// How to group them?
select new { //How to take and return the counts?};

SQL Query Performance with count

I have 2 tables, COMPANY and EMPLOYEE.
COMPANY_ID is the primary key of the COMPANY table and foreign key for EMPLOYEE table. The COMPANY_ID is a 10 digit number. We are generate a 3 number combination and query the database.
The select statement has regex to bulk load the company based on COMPANY_ID. The query is executed multiple times with different patterns
i.e.
regexp_like(COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)') .
Existing query looks something like this -
select *
from COMPANY company
where regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
The new requirement is to retrieve the company information along with the employee count. For example if a company has 10 employees, then the query should return all the columns of the COMPANY table, along with employee count i.e. 10
This is the select statement that I came up with -
select
nvl(count_table.cont_count, 0), company.*
from
COMPANY company,
(select company.COMPANY_ID, count(company.COMPANY_ID) as cont_count
from COMPANY company, EMPLOYEE employee
where regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
and company.CONTACT_ID = employee.CONTACT_ID
group by (company.COMPANY_ID)) count_table
where
regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
and count_table.COMPANY_ID(+)= company.COMPANY_ID
Above query works, but it takes double the time compared to the previous statement. Is there a better way to retrieve the employee count?
Note: Oracle database is in use.
You don't need to execute that expensive REGEXP_LIKE twice:
select nvl(count_table.cont_count,0),company.*
from COMPANY company
,( select employee.COMPANY_ID, count(employee.COMPANY_ID) as cont_count
from EMPLOYEE employee
group by (employee.COMPANY_ID)
) count_table
where regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
and count_table.COMPANY_ID(+)= company.COMPANY_ID
Or you could use a scalar subquery:
select company.*
, (select count(*)
from employee e
where e.company_id = c.company_id
)
from COMPANY c
where regexp_like(c.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
And personally I would ditch the slow REGEXP_LIKE for something like:
where substr(c.company_id,1,3) between '000' and '009'
The derived table does not add value, thus I would get rid of it and use a scalar query (because I do not know all of your columns in the company table to properly do a group by):
select c.*,
nvl(
(select count(1)
from employee emp
where emp.company_id = c.company_id
),0) employee_count
from company c
where regexp_like(c.company_id, '^(000|001|002|003|004|005|006|007|008|009)')
Also, if performance is still an issue, I would consider modifying your where statement to not use a regexp.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Addendum
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I see that the question explicitly identifies that the employee table has company_id as a foreign key. Since this is clarified, I am removing this statement:
The data model for these tables is not intuitive (would you not have
company_id as a foreign key in the employees table?).

Need to select column from subquery into main query

I have a query like below - table names etc. changed for keeping the actual data private
SELECT inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
I am selecting records from Invoice based on Order. i.e. all records from Invoice which are common with order records for today, based on those 3 columns...
Now I want to select Order_Num from Order in my select query as well.. so that I can use the whole thing to insert it into totally seperate table, let's say orderedInvoices.
insert into orderedInvoices(seq_no,..same columns as Inv...,Cr_dt)
(
SELECT **Order.Order_Num**, inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
)
?? - how to do I select that Order_Num in main query for each records of that sub query?
p.s. I understand that trunc(cr_dt) will not use index on cr_dt (if a index is there..) but I couldn't select records unless I omit the time part of it..:(
If the table ORDER1 is unique on CARRIER, PRO and N_DT you can use a JOIN instead of IN to restrict your records, it'll also enable you to select whatever data you want from either table:
select order.order_num, inv.*, trunc(sysdate)
from Invoice inv
join order ord
on inv.carrier = ord.carrier
and inv.pro = ord.pro
and inv.ndate = ord.n_dt
where trunc(order.cr_dt) = trunc(sysdate)
If it's not unique then you have to use DISTINCT to deduplicate your record set.
Though using TRUNC() on CR_DT will not use an index on that column you can use a functional index on this if you do need an index.
create index i_order_trunc_cr_dt on order (trunc(cr_dt));
1. This is a really bad name for a table as it's a keyword, consider using ORDERS instead.

Resources