Optimize laravel join query - laravel

Is there anyone who can optimize below query please. Mids table has records 166 and orders table has records 350000 (0.35 million). Query is taking more than one minute on local as well as in database. Please check below query code:
DB::table('mids')->join('orders', 'orders.gateway_id', '=', 'mids.gateway_id')
->select(DB::raw('mids.*', DB::raw('SUM(orders.order_total) as sum')))
->addSelect(DB::raw('sum(case when orders.order_status = "2" then 1 else 0 end) as mid_count'))
->addSelect(DB::raw('sum(case when orders.order_status = "7" then 1 else 0 end) as decline_per'))
->groupBy('mids.id')->get();

hey brother instead of multiple DB::raw and addselect() you cam simply use it in this way:
DB::table('mids')->join('orders', 'orders.gateway_id', '=', 'mids.gateway_id')
->select(DB::raw('mids.*, SUM(orders.order_total) as sum,
sum(case when orders.order_status = "2" then 1 else 0 end) as mid_count,
sum(case when orders.order_status = "7" then 1 else 0 end) as decline_per'))
->groupBy('mids.id')->get();
But i suggest use pagination if you are fetching large data and for pagination docs will be more helpful: Database: Pagination

Related

Laravel Eloquent complex Subquery

I have Following query. I want to rewrite this into Laravel Eloquernt.
SELECT COUNT(*) AS CNT FROM CashTransaction AS A
WHERE A.Flag=0
AND A.IsCancel=0
AND A.Amount-ifnull((
SELECT sum(ifnull(Bills.Amount,0))
FROM CashTransaction AS Bills
WHERE A.ContractID=Bills.ContractID
AND Bills.Flag=2
AND Bills.IsCancel=0),0) > 0
So I could write upto
$commissionDepositCount = CashTransaction::where('Flag', 0)
->where('IsCancel',0)
->where('Amount','>',function($query){
$query->from('CashTransaction')
})
->when($user->Level < 5,function($query) use($user){
$query->where('SenderID',$user->id);
})
->count()
I cannot find how to write subqueries that
A.Amount-ifnull((
SELECT sum(ifnull(Bills.Amount,0))
FROM CashTransaction AS Bills
WHERE A.ContractID=Bills.ContractID
AND Bills.Flag=2
AND Bills.IsCancel=0),0) > 0
Can Anyone help me with this?

how to select all on laravel query builder?

(1)
DB::query()
->select(*) <----how to write it's error
->addSelect(DB::raw('SUM(CASE WHEN B.approve IS NULL THEN 0 ELSE 1 END) as Ashowcount'))
->addSelect(DB::raw('SUM(B.approve) as Yshow'))
->from(a16 as A)
.....
(2)
DB::table(a16 as A')
->Select(DB::raw('SUM(CASE WHEN B.approve IS NULL THEN 0 ELSE 1 END) as Ashowcount'))
->addSelect(DB::raw('SUM(B.approve) as Yshow'))
...... <---just select two column
I want to ask how can I select all from a16 with above two query code?
I need use addselect to add the DB:raw code
I only can type one by one just like
->select('A.id','A.s_main','A.s_brand','A.s_model','A.s_price','A.s_count','A.s_unit','A.s_location','A.s_geography','A.s_location','A.u_id','A.classify','A.s_boss','A.route','A.created_at')
I feel it's some no efficiency.
How can I select all column easily?
DB::query()
->select('A.*')
->addSelect(DB::raw('SUM(CASE WHEN B.approve IS NULL THEN 0 ELSE 1 END) as Ashowcount'))
->addSelect(DB::raw('SUM(B.approve) as Yshow'))
->from(a16 as A)

postgres inner join sum for when no relation exists

I am trying to run a simple query where I get a sum of gardeners who have zero support visits. I would like to add other cases, but first I would like to get this zero thing right. This is what I have come up with:
Gardener.from(Gardener.joins(:support_visits).group(:gardener_id).select("CASE WHEN count(gardener_id) = 0 THEN 1 END AS zero_count"),:t).select("sum(t.zero_count) as tot_zero_count")
Which gives me the following sql query:
SELECT sum(t.zero_count) as tot_zero_count
FROM
(
SELECT CASE WHEN count(gardener_id) = 0 THEN 1 END AS zero_count
FROM "gardeners" INNER JOIN "support_visits"
ON "support_visits"."gardener_id" = "gardeners"."id"
GROUP BY gardener_id
) t
The query runs but gives me nil.
Your current query uses count(gardener_id) = 0 which is never true because any group will have at least one record. Instead, you can LEFT JOIN the gardeners table to the support_visits table. Any gardener which does not appear in the support_visits table will not match to a visit, leaving a null value which you can then count.
SELECT SUM(CASE WHEN "support_visits"."gardener_id" IS NULL THEN 1 ELSE 0 END) AS zero_count
FROM "gardeners" LEFT JOIN "support_visits"
ON "support_visits"."gardener_id" = "gardeners"."id"
Here is the Ruby ActiveRecord code for this query:
Gardener.from(Gardener.joins("LEFT JOIN `support_visits` ON gardeners.id = support_visits.gardener_id").select("SUM(CASE WHEN "support_visits"."gardener_id" IS NULL THEN 1 ELSE 0 END) AS zero_count"))

Return only one row from Oracle SQL, using outer join and case statement

I'm trying to figure out how to just return one row per result, even if there are multiple activities ('act's) per result. I've read and searched to no avail.
What I want:
Date Site Result act1 act2
1985-06-10 1008 NT6 5 10
What I get:
Date Site Result act1 act2
1985-06-10 1008 NT6 5
1985-06-10 1008 NT6 10
Here's my (example) code, which I know is not broken, but it's the path I tried. I just don't know how to obtain what I want.
SELECT
t."Date",
t."Site",
t."Result",
CASE
WHEN a.Type = 'act1'
THEN a.Count
END AS "act1",
CASE
WHEN a.Type = 'act2'
THEN a.Count
END AS "act2"
FROM
(
SELECT Sample.SAMPLE_ID,
Sample.Date,
Sample.Site,
Sample.Result
FROM Sample
WHERE Sample.Date is Between then and now
) t
LEFT OUTER JOIN
ACTIVITY
ON (ACTIVITY.SAMPLE_ID = t.SAMPLE_ID)
here you go
select t."Date", t."Site", t."Result",
sum(case when a.Type = 'act1' then a.Count else 0 end ) AS act1,
sum(case when a.Type = 'act2' then a.Count else 0 end ) AS act2
from sample left outer join activity
on (activity.sample_id = t.sample_id)
where sample.date is between then and now
and don't use braces on column names.

Using Linq (nHibernate) to perform a Case statement with Counts

I'm sure this is one has done the houses a few times but i've never found a solution...
So is it possible to do something like this using nHibernate 3 with preferably Linq:
SELECT
COUNT(CASE WHEN IsWithdrawn = 1 THEN 1 END) AS WithdrawnCount,
COUNT(CASE WHEN IsWithdrawn = 0 THEN 1 END) AS ViewAllCount
FROM Tutorials
I'm pretty sure that is isn't possible and that the best solution is to opt just for sql in this case... but maybe there is something new in nHibernate 3.1 that can do this with, even using queryover?
thanks
You can do it with HQL, which is almost the same as SQL:
SELECT
SUM(CASE WHEN IsWithdrawn = 1 THEN 1 ELSE 0 END) AS WithdrawnCount,
SUM(CASE WHEN IsWithdrawn = 0 THEN 1 ELSE 0 END) AS ViewAllCount
FROM Tutorials
(I'm not sure if the COUNT would work, I'm sure SUM does)
Here's a LINQ version that should work too:
session.Query<Tutorial>()
.GroupBy(x => x.IsWithdrawn)
.Select(x => new { x.Key, Count = x.Count() })
You can use Projections.Conditional with Criteria or QueryOver, but it's more work.
You can get the desired result with QueryOver, although it will be slower due to the subqueries.
var sums = repo.Session.QueryOver<Tutorials>()
.SelectList(list => list
.SelectSubQuery<Tutorials>(NHibernate.Criterion.QueryOver.Of<Tutorials>()
.Where(t => t.IsWithdrawn)
.ToRowCountQuery())
.SelectSubQuery<Tutorials>(NHibernate.Criterion.QueryOver.Of<Tutorials>()
.ToRowCountQuery())
)
.Take(1) // we want only one row in our result. In SQL I would use " from dummy".
.List<object[]>();
Explanation:
I use two detached QueryOvers. The first one counts the rows in Tutorials where IsWithdrawn = true, the second once counts all rows. The two detached QueryOvers are then used as SubQueries in a normal QueryOver with a Projection (SelectList).
Here is the generated SQL:
SELECT TOP (1)
(SELECT count(*) as y0_ FROM [Tutorials] this_0_
WHERE this_0_.IsWithdrawn = True) as y0_,
(SELECT count(*) as y0_ FROM [Tutorials] this_0_) as y1_
FROM [Tutorials] this_;

Resources