Laravel Eloquent - How to create queries with sub query and if satement - mysql

Here is my query
SELECT
IF((SELECT COUNT(*) FROM tablename t WHERE t.field1 = tablename.field1 AND t.field2 IN (50,55,58,60)) = 0,1,0) AS b,
field3,
field4,
FROM tablename
WHERE ProductId = ?
How do I convert it to laravel eloquent?

It would be better if you have shown what you've tried.
That said, this should work:
$result = App\TablenameModel::where('ProductId', 'your_value_here')
->select(
\DB::raw('IF((SELECT COUNT(*) FROM tablename t WHERE t.field1 = tablename.field1 AND t.field2 IN (50,55,58,60)) = 0,1,0) AS b'),
'field3',
'field4'
)
->get();

Related

Need help converting sql query into laravel query

I need the following sql query into laravel query or how can I run into laravel as it is. thanks
SELECT t.*
FROM (SELECT client_id,product_name, max(real_date) AS max_date
FROM api_hilbertis.transactions
WHERE active = 1 AND real_date <= '2019-03-01'
GROUP BY client_id, product_name) AS m
INNER JOIN api_hilbertis.transactions AS t
ON t.client_id = m.client_id
AND t.product_name = m.product_name
AND t.real_date = m.max_date
AND active = 1
ORDER BY real_date DESC;
You can use laravel raw queries.
Example HERE
So for your case it we could write something like:
$results = DB::select( DB::raw("
SELECT t.*
FROM (SELECT client_id,product_name, max(real_date) AS max_date
FROM api_hilbertis.transactions
WHERE active = 1 AND real_date <= '2019-03-01'
GROUP BY client_id, product_name) AS m
INNER JOIN api_hilbertis.transactions AS t
ON t.client_id = m.client_id
AND t.product_name = m.product_name
AND t.real_date = m.max_date
AND active = 1
ORDER BY real_date DESC"
));
EDIT: example with variables:
$someVariable = $request->input('some_variable');
$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"),
['somevariable' => $someVariable,]
);

Trying to convert a query to eloquent

I have the following SQL:
SELECT arv.*
FROM article_reference_versions arv
INNER JOIN (SELECT `order`,
Max(`revision`) AS max_revision
FROM article_reference_versions
WHERE `file` = '12338-230180-1-CE.doc'
GROUP BY `file`,
`order`) AS b
ON arv.order = b.order
AND arv.revision = b.max_revision
WHERE arv.file = '12338-230180-1-CE.doc'
I need to convert this to Eloquent, so that I can properly access the data in object form. I tried doing it as such,
$s = Models\EloArticleReferenceVersion::select(
'SELECT arv.*
FROM article_reference_versions arv
INNER JOIN (
SELECT `order`, max(`revision`) as max_revision
FROM article_reference_versions
WHERE file = ? group by `file`, `order`) AS b
ON
arv.order = b.order AND arv.revision = b.max_revision
WHERE arv.file = ?',
[
'12338-230180-1-CE.doc',
'12338-230180-1-CE.doc'
])->get();
dd($s);
But I'm running into a plethora of issues, one after another. I figured it'd be easier to just convert this into an eloquent query, looking for some help with this.
DB Query to Query using Eloquent.
$query = EloArticleReferenceVersion::query()
->join(DB::raw('( SELECT `order`,Max(`revision`) AS max_revision FROM article_reference_versions WHERE `file` = '12338-230180-1-CE.doc' GROUP BY `file`, `order`) as sub_table'), function($join) {
$join->on('sub_table.order', '=', 'article_reference_versions.order');
$join->on('sub_table.max_revision ', '=', 'article_reference_versions.revision');
})
->where('article_reference_versions.file', '=', '12338-230180-1-CE.doc' )
->get();
Not Tested

How do I select columns from results of union of tables using laravel query builder?

I am trying to convert my mysql statement into laravel query builder. In the following query I am trying to do GROUP BY and ORDER BY on the columns which are fetched from the result of UNION-ing three tables
staff_task_history_calibrate
staff_task_history_samples
staff_task_history_measures
Have you guys come across anything similar to it? If yes, could you please shed some light on my issue?
SELECT staff_name, task_id, task_type, task_desc, SUM(task_multiplier)
FROM
(
(
select CONCAT(S.first_name," ",S.last_name) as staff_name,
`STHC`.`task_id`, IFNULL(T.type, "-") as task_type,
`T`.`description` as `task_desc`,
STHC.task_multiplier
from `staff_task_history_calibrate` as `STHC`
inner join `staffs` as `S` on `STHC`.`staff_id` = `S`.`staff_id` inner join `tasks` as `T` on `STHC`.`task_id` = `T`.`id`
)
union
(
select CONCAT(S.first_name," ",S.last_name) as staff_name,
`STHS`.`task_id`, IFNULL(T.type, "-") as task_type,
`T`.`description` as `task_desc`,
STHS.task_multiplier
from `staff_task_history_samples` as `STHS`
inner join `staffs` as `S` on `STHS`.`staff_id` = `S`.`staff_id` inner join `tasks` as `T` on `STHS`.`task_id` = `T`.`id`
)
union
(
select CONCAT(S.first_name," ",S.last_name) as staff_name,
`STHM`.`task_id`, IFNULL(T.type, "-") as task_type,
`T`.`description` as `task_desc`,
STHM.task_multiplier
from `staff_task_history_measures` as `STHM`
inner join `staffs` as `S` on `STHM`.`staff_id` = `S`.`staff_id` inner join `tasks` as `T` on `STHM`.`task_id` = `T`.`id`
)
) combined_tables
GROUP BY staff_name, task_type, task_desc
ORDER BY staff_name, task_type, task_desc;
Difficult for me to test, but try:
// Build up the sub-queries
$sub1 = DB::table('staff_task_history_calibrate AS STHC')
->select(DB::raw(
'CONCAT(S.first_name," ",S.last_name) as staff_name',
'STHC'.'task_id', 'IFNULL(T.type, "-") as task_type',
'T'.'description' as 'task_desc', 'STHC.task_multiplier')
)->join('staffs AS S', 'STHC.staff_id', '=', 'S.staff_id')
->join('tasks AS T', 'STHC.task_id', '=', 'T.id');
$sub2 = DB::table('staff_task_history_samples AS STHS')
->select(DB::raw(
'CONCAT(S.first_name," ",S.last_name) as staff_name',
'STHS'.'task_id', 'IFNULL(T.type, "-") as task_type',
'T'.'description' as 'task_desc', 'STHS.task_multiplier')
)->join('staffs AS S', 'STHS.staff_id', '=', 'S.staff_id')
->join('tasks AS T', 'STHS.task_id', '=', 'T.id');
$sub3 = DB::table('staff_task_history_measures AS STHM')
->select(DB::raw(
'CONCAT(S.first_name," ",S.last_name) as staff_name',
'STHM'.'task_id', 'IFNULL(T.type, "-") as task_type',
'T'.'description' as 'task_desc', 'STHM.task_multiplier')
)->join('staffs AS S', 'STHM.staff_id', '=', 'S.staff_id')
->join('tasks AS T', 'STHM.task_id', '=', 'T.id');
// Add the unions
$allUnions = $sub1->union($sub2)->union($sub3); // (Check the documentation for Unions in Query Builder)
// Get the results
$results = DB::table(DB::raw("({$allUnions->toSql()}) as combined_tables"))
->select('staff_name, task_id, task_type, task_desc')
->sum('task_multiplier')
->mergeBindings($allUnions) // We need to retrieve the underlying SQL
->groupBy('staff_name')
->groupBy('task_type')
->groupBy('task_desc')
->orderBy('staff_name')
->orderBy('task_type')
->orderBy('task_desc')
->get();
(If what you have works, I'd keep it.)

how to sum amount from two different tables in one query without using union mysql

SELECT SUM(amount_paid) AS total_session FROM session
WHERE session.date = '2016-02-03' AND session.payment_status = 'PAID'
UNION
SELECT SUM(amount_paid) AS total_subscription FROM subscription
WHERE subscription.date_enrolled = '2016-02-03' AND subscription.payment_status = 'PAID'
I just want to display the result in two different columns with alias total_session and total_subscription. How can I do that using union?
Instead of a UNION, put each query as a subquery in a main SELECT
SELECT
(SELECT SUM(amount_paid) FROM session
WHERE session.date = '2016-02-03' AND session.payment_status = 'PAID') AS total_paid,
(SELECT SUM(amount_paid) FROM subscription
WHERE subscription.date_enrolled = '2016-02-03' AND subscription.payment_status = 'PAID') AS total_subscription
In that case, you can try doing a fake join like
SELECT xx.total_session, yy.total_subscription
FROM (
SELECT '1' as ID, SUM(amount_paid) AS total_session FROM session
WHERE session.date = '2016-02-03' AND session.payment_status = 'PAID') xx
JOIN (SELECT '1' as ID, SUM(amount_paid) AS total_subscription FROM subscription
WHERE subscription.date_enrolled = '2016-02-03' AND subscription.payment_status = 'PAID') yy
ON xx.ID = yy.ID;

How to join multiple count(*) queries?

Is there a way to join multiple count(*) queries to a single one? I know that i don't need to prepare the last two queries two times but that's not what the question is about. I have no idea how to do this in a correct way.
$sth = $this->_db->prepare('SELECT count(*) FROM posts WHERE topicid = ?');
$sth->execute( array( $this->_id ) );
$numPosts = $sth->fetch(\PDO::FETCH_ASSOC);
$sth = $this->_db->prepare('SELECT count(*) FROM topic_activity WHERE topicid = ?');
$sth->execute( array( $this->_id ) );
$numViews = $sth->fetch(\PDO::FETCH_ASSOC);
$sth = $this->_db->prepare('SELECT count(*) FROM topic_activity WHERE topicid = ? AND likes = 1');
$sth->execute( array( $this->_id ) );
$numLikes = $sth->fetch(\PDO::FETCH_ASSOC);
$sth = $this->_db->prepare('SELECT count(*) FROM topic_activity WHERE topicid = ? AND likes = -1');
$sth->execute( array( $this->_id ) );
$numDislikes = $sth->fetch(\PDO::FETCH_ASSOC);
SELECT count_post, topic_activity
FROM(
SELECT count(*) AS count_post, NULL AS topic_activity FROM posts WHERE topicid = ?
UNION
SELECT NULL AS count_post, count(*) AS topic_activity FROM topic_activity WHERE topicic =?
) T
GROUP by count_post, topic_activity
let me know if it works
Although the answer of user3106988 'works', I would have gone for a more 'vertical' approach (and also store the id in a variable so you only need to pass it once, could be this doesn't work in your environment though, so could be you'll need to replace the #id's with 4 question marks, but hopefully not) :
SET #id = ?;
SELECT info = 'Posts', count(*) FROM posts WHERE topicid = #id
UNION ALL
SELECT info = 'Views', count(*) FROM topic_activity WHERE topicid = #id
UNION ALL
SELECT info = 'Likes', count(*) FROM topic_activity WHERE topicid = #id AND likes = 1
UNION ALL
SELECT info = 'DisLikes', count(*) FROM topic_activity WHERE topicid = #id AND likes = -1
But that returns 4 records where you'll then need to extract the data out by means of the info field. So, building on the idea of user3106988's answer to return just 1 record with all the info in different fields you could actually go for the likes & disklikes in as little effort as below. Should be quite fast.
SET #id = ?;
SELECT SUM(count_posts) as count_posts,
SUM(views) as views,
SUM(likes) as likes,
SUM(dislikes) as dislikes
FROM(
SELECT COUNT(*) as count_posts,
0 as views,
0 as likes,
0 as dislikes
FROM posts
WHERE topicid = #id
UNION ALL
SELECT 0 as count_posts,
COUNT(*) as views,
SUM(Case WHEN likes = 1 THEN 1 ELSE 0 END) as likes,
SUM(Case WHEN likes = -1 THEN 1 ELSE 0 END) as dislikes
FROM topic_activity
WHERE topicid = #id
) T;