How can I convert this SQL query to Laravel Eloquent? - php

One of our teams asked this question earlier today, and there aren't any right answers still. Perhaps the way he worded the question wasn't correct—all in all, this is the SQL query I want to convert to Laravel Eloquent:
SELECT * FROM drivers
where driver_number
NOT IN (SELECT driver_number FROM buses)
AND station_id = 2 OR driver_number = 'Dr_02'

Try this:
Driver::whereNotIn('driver_number', Buse::select('driver_number'))
->where('station_id', 2)
->orWhere('driver_number', 'Dr_02');
If the Buse select gives you an error, add the get method at the end of it:
Buse::select('driver_number')->get()

Related

How do I write eloquent query for retrieving multiple rows who have max versions?

I want to write a query to retrieve rows who have a max version for their particular groups
For eg:
English Basic has 4 versions(test_id:1,2,4,7). But I want to retrieve the one with the max version
with this I also want to retrieve other such records of max version
I want this result
Mom Basic 20 1(version)(id:5)
Mom Intermediate 30 1(version)(id:6)
English Basic 20 5(version)(id:7)
Thanks and Let me know if you have any doubts
Here is what I've tried:
I got the SQL query:
SELECT *, MAX(`version`) FROM `test` GROUP BY `test_name`,`sub_category`,`test_type`
But I am not able to properly write it in laravel (throws syntax error)
Here are my laravel tries:
$test = Test::selectRaw('*, MAX(version) GROUP BY `test_name` ')->get();
$test = Test::selectRaw('*')->groupBy('sub_category')->toSql();
and so on
P.S. Don't worry about the format of commas or quotes as I tried all the combinations with this. Just not able to figure out what is the write code
I did not try this one. But I think you can do this. What you meant by unique is not clear.
Test::where('version', Test::max('version'))->get();
Please try this,
Mysql
select test_type,test_name,sub_category,time,max(version) as version
from table_name group by test_name,sub_categoryorder by version ;
Laravel
$result=DB::select(DB::raw("select test_type,test_name,sub_category,time,max(version) as version
from table_name group by test_name,sub_categoryorder by version"));
Check Fiddle
$maxVersion = Test::orderBy('version', 'desc')->first(); // gets the whole row
Here is the solution I found:
$test = DB::select(DB::raw("
SELECT * FROM test a
INNER JOIN (SELECT test_type, test_name,sub_category, MAX(version) AS maxversion
FROM test GROUP BY test_type,test_name,sub_category) b
ON a.test_type=b.test_type
AND a.test_name=b.test_name
AND a.sub_category=b.sub_category
AND a.version=b.maxversion"));
There is no way to easily translate this into eloquent if you could do it then please post it here. Also you need to make sql strict in your config->database file as false to run this as it has some issue with group by

(Laravel) can't use group by with order by [duplicate]

This question already has answers here:
Group by not working - Laravel
(8 answers)
Closed 3 years ago.
I'm trying to use order by without adding the order column in groupby, it only works if I execute it directly from the database but from laravel I get database error
I made this eloquent code
Comment::select('product_id')->where('shop_name', $shop)->groupby('product_id')->distinct()->orderBy('created_at')->paginate(12)
it will product the following query
select distinct DISTINCT(product_id) from comments where shop_name
= 'shopname' group by product_id order by created_at asc limit 12 offset 0
if I rub the above query directly in database it works
but if I use Laravel eloquent code it fires this error
SQLSTATE[42000]: Syntax error or access violation: 1055
'areviews_areviewzappz.comments.created_at' isn't in GROUP BY (SQL:
select distinct DISTINCT(product_id) from comments where shop_name
= 'shopname' group by product_id order by created_at asc limit 12 offset 0)
how can I solve this issue ?
The issues is that you SHOULD really include the ORDER BY in the GROUP BY list as this is best practise.
The reason it works when you are on the the sql mode set to ''. However, Laravel by default (I think) has Strict as TRUE,
You have 2 options:
Add the created_at to the GROUP BY clause (Recommended)
Change the strict mode to false
A bit more info on the 2nd option:
How can I solve incompatible with sql_mode=only_full_group_by in laravel eloquent?
You can group it after you have retrieved the results rather than in the MySQL query - so you group the collection after it has been retrieved, not the table entries in the query itself.
Comment::select('product_id')
->where('shop_name', $shop)
->distinct()
->orderBy('created_at')
->paginate(12)
->groupBy('product_id')
Laravel collection groupBy method: https://laravel.com/docs/5.7/collections#method-groupby
Related post: Laravel Query Buider Group By Not Getting All The Records

MYSQL query which years have records

I have a table with a date field, I need to find out which years have records and output only the list of the years e.g.( [2011,2012,2013] ), the only way I have imagined is to get all rows and then analyze in a php loop.
Does anybody knows a way to achieve this with pure SQL, or will I have to analyze the data with a php function?
SELECT DISTINCT YEAR(datecolumn) FROM yourtable
YEAR() is a MySQL function that will return the year corresponding to the current date stored in your column.
SELECT DISTINCT will return only unique values for the result of YEAR(datecolumn). More information can be found in this tutorial
If you need to output the list itself in one SQL query Linger's answer is clearly the way to go.
Try doing:
SELECT YEAR(dateColumn)
FROM yourTable
GROUP BY YEAR
You state that you want a list like [2011,2012,2013]. The following SQL Fiddle demonstrates how you can achieve such a thing in one field:
SELECT CONCAT('[', GROUP_CONCAT(MQ.MyYear), ']') AS YearsList
FROM
(
SELECT DISTINCT YEAR(MyDateField) AS MyYear
FROM MyTable
) AS MQ
In the above example I use a sub query to get all of the unique years found in the table. Then I use GROUP_CONCAT to combine them all together separating each year with a ,. Then I use CONCAT to add the brackets at the front and end of the string.

Get PHP MySQL PDO column table name as a result of a join [duplicate]

This question already has answers here:
How to resolve ambiguous column names when retrieving results?
(11 answers)
Closed 2 years ago.
I have fields that have the same name in different tables that I'm joining. Such as ticket.status, user.status and transaction.status. At the moment the query returns just status.
How can I get the table name in such a way that it stops similar field names from overwriting and so I can tell the difference between the fields.
Simply put:
$data = array($eventId);
$statement = $this->db->prepare("SELECT * FROM ticket, user, transaction
WHERE ticket.eventId = ?
AND ticket.userId = user.userId
AND ticket.transactionId = transaction.transactionId");
$statement->execute($data);
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
In my research I've found the constant PDO::ATTR_FETCH_TABLE_NAMES that looks like it could help, but I do not know how to implement ( I assume through $statement->setAttribute(); somehow).
I also have concerns that it will not work, as the PHP documentation mentions it is dependent on the driver.
Thanks
Just add new aliases to your select statements
$statement = $this->db->prepare("
SELECT *, ticket.status AS ticket_status, user.status AS user_status, transaction.status AS transaction_status
FROM ticket, user, transaction
WHERE ticket.eventId = ?
AND ticket.userId = user.userId
AND ticket.transactionId = transaction.transactionId
");
Then you can do
$rows[0]['user_status'];
$rows[0]['ticket_status'];
$rows[0]['transaction_status'];
If you are really concern by performance, the quantity of data returned will be greater so instead of adding new aliases you can select every single columns and while you do so put an alias on the status column.
Why not change your to actually join instead:
SELECT
t.status as ticket_status, u.status as user_status, tr.status as trans_status
FROM
ticket as t
inner join user as u on t.userId = u.userId
inner join transaction as tr on t.transactionId = tr.transactionId
where
t.eventId = ?
You don't even need to cast the tables using as something but I find it's neater.
Note, its the casting of the columns that will actually fix this issue, not the join method.
The most obvious comment is "don't do it, that's why aliases exist". But there's still a good underlying question: does MySQL send information about where a result-set column comes from (table, view or calculated)?
Apparently, it does, since the PDOStatement object has an experimental method called getColumnMeta(). I've been testing and it returns an associative array where the table key
contains the source table if column comes from a table or view
is an empty string if the column is calculated
Of course, I'd stick to aliases anyway. Being able to use associative arrays is a killer feature for me.

Get number of rows in MySQL [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Fastest way to count exact number of rows in a very large table?
What query do I use to get the number of rows that share a common specification.
Example: The number of rows where idpost = 3
You can use COUNT() documented here.
SELECT COUNT(1) FROM posts WHERE idpost = 3
EDIT: Updated according to dbf's suggestion.. Make sure you distinguish between COUNT(*) and COUNT(1), discussed here.
The query looks like this:
SELECT count(*) FROM some_table WHERE (conditions);
In your example:
SELECT count(*) FROM some_table WHERE idpost=3;
More on counting rows in MySQL: MySQL 5.6 Reference Manual: 3.3.4.8. Counting Rows
EDIT:
If you were wondering, which way of counting all rows is better (count(*) or count(1)), see this: What is better in MYSQL count(*) or count(1)?.
Try
SELECT
COUNT(*) as NumberRows
FROM
your_table_name_here
WHERE
idpost = 3
;
Consider learning SQL:
select count(*) from mytable where idpost=3
the select count(*) function grabs the number of rows that meet a certain criteria - define that in the where statement.
http://dev.mysql.com/doc/refman/5.1/en/counting-rows.html - read here

Categories