How to make this query in laravel Query builder - laravel

SELECT
p.*, (IF(dp.Rate, dp.Rate, p.Rate)) AS Rate
FROM
visp.packages p LEFT JOIN (SELECT
*
From
visp.dealer_packages
Where
DealerID = 56 OR DealerID = 0
) dp on dp.PackageID = p.packageID
WHERE p.Status = 1 AND (IsPublic = 1 AND dp.Status is NULL OR dp.Status = 1) AND IsDealerCanAdd = 1 ORDER BY
p.PackageOrdering
How to make this query in laravel-querybuilder ?

Related

how to write this sql query to codeigniter query

SELECT 1 + (SELECT count( * ) FROM student_rank a WHERE a.obtained_total_mark > b.obtained_total_mark ) AS rank FROM student_rank b WHERE student_id = '5' ORDER BY rank LIMIT 1 ;
convert search query
use
$this->db->query("SELECT 1 + (SELECT count( * ) FROM student_rank a WHERE a.obtained_total_mark > b.obtained_total_mark ) AS rank FROM student_rank b WHERE student_id = '5' ORDER BY rank LIMIT 1")

Conditional data selection in oracle

I have a set of data by using query and in this data I need to select some data according to following condition
If SIGNSTAT = 4 then select all row which have SIGNSTAT = 4
Otherwise select latest create date row data.
Please help to found the data
My query is as
WITH CTE AS(SELECT C2C.NO AS CONTRACTNO,
C.BRANCH,
C.IDCLIENT,
--C.PAN,
C.NAMEONCARD,
C.CREATEDATE,
C.SIGNSTAT,
ROW_NUMBER ()
OVER (PARTITION BY C2C.NO ORDER BY C.CREATEDATE DESC)
AS ROW_NUM
FROM A4M.TCONTRACTCARDITEM C2C, A4M.TCARD C,A4M.TREFERENCECARDPRODUCT RCP
WHERE 1 = 1 AND C.BRANCH = C2C.BRANCH AND C.PAN = C2C.PAN AND C2C.NO = '700000075333'
AND C.BRANCH = RCP.BRANCH AND C.CARDPRODUCT = RCP.CODE
AND UPPER(RCP.NAME) LIKE '%SUPPL%'
)
SELECT * FROM CTE
--WHERE ROW_NUM = 1
Result set:
CONTRACTNO BRANCH IDCLIENT NAMEONCARD CREATEDATE SIGNSTAT ROW_NUM
700000075333 1 1215995 SAMIR CHANDRA DHAR 14-Jul-19 4 2
700000075333 1 1215995 SAMIR CHANDRA DHAR 20-Aug-19 3 1
Is this what you need?
WITH data AS(SELECT C2C.NO AS CONTRACTNO,
C.BRANCH,
C.IDCLIENT,
--C.PAN,
C.NAMEONCARD,
C.CREATEDATE,
C.SIGNSTAT,
ROW_NUMBER ()
OVER (PARTITION BY C2C.NO ORDER BY C.CREATEDATE DESC)
AS ROW_NUM
FROM A4M.TCONTRACTCARDITEM C2C, A4M.TCARD C,A4M.TREFERENCECARDPRODUCT RCP
WHERE 1 = 1 AND C.BRANCH = C2C.BRANCH AND C.PAN = C2C.PAN AND C2C.NO = '700000075333'
AND C.BRANCH = RCP.BRANCH AND C.CARDPRODUCT = RCP.CODE
AND UPPER(RCP.NAME) LIKE '%SUPPL%'
), cnt AS (SELECT COUNT(1) total
FROM data
WHERE SIGNSTAT=4)
SELECT *
FROM data
WHERE SIGNSTAT=4
UNION ALL
SELECT *
FROM data
JOIN cnt
ON cnt.total=0
WHERE data.ROW_NUM = 1
I got the desire result by following query
WITH data AS(SELECT C2C.NO AS CONTRACTNO,
C.BRANCH,
C.IDCLIENT,
C.PAN,
C.NAMEONCARD,
C.CREATEDATE,
C.SIGNSTAT,
ROW_NUMBER ()
OVER (PARTITION BY C2C.NO ORDER BY C.CREATEDATE DESC)
AS ROW_NUM
FROM A4M.TCONTRACTCARDITEM C2C, A4M.TCARD C,A4M.TREFERENCECARDPRODUCT RCP
WHERE 1 = 1 AND C.BRANCH = C2C.BRANCH AND C.PAN = C2C.PAN AND C2C.NO = '700000075333'
AND C.BRANCH = RCP.BRANCH AND C.CARDPRODUCT = RCP.CODE
AND UPPER(RCP.NAME) LIKE '%SUPPL%') SELECT CONTRACTNO,BRANCH,IDCLIENT FROM data WHERE SIGNSTAT=4 UNION ALL (SELECT CONTRACTNO,BRANCH,IDCLIENT FROM data WHERE data.ROW_NUM = 1 MINUS SELECT CONTRACTNO,BRANCH,IDCLIENT FROM data WHERE SIGNSTAT=4)
You can achieve this with minor change in your original query. Use CASE WHEN as following:
WITH CTE AS(SELECT C2C.NO AS CONTRACTNO,
C.BRANCH,
C.IDCLIENT,
--C.PAN,
C.NAMEONCARD,
C.CREATEDATE,
C.SIGNSTAT,
CASE WHEN C.SIGNSTAT = 4 THEN 1 ELSE ROW_NUMBER ()
OVER (PARTITION BY C2C.NO ORDER BY C.CREATEDATE DESC) END
AS ROW_NUM
FROM A4M.TCONTRACTCARDITEM C2C, A4M.TCARD C,A4M.TREFERENCECARDPRODUCT RCP
WHERE 1 = 1 AND C.BRANCH = C2C.BRANCH AND C.PAN = C2C.PAN AND C2C.NO = '700000075333'
AND C.BRANCH = RCP.BRANCH AND C.CARDPRODUCT = RCP.CODE
AND UPPER(RCP.NAME) LIKE '%SUPPL%'
)
SELECT * FROM CTE
WHERE ROW_NUM = 1
Cheers!!

Multiple whereHas calls are not being aggregated together

I've got multiple calls to whereHas() on an instance of \Illuminate\Database\Query\Builder ($cars):
$cars->whereHas("finance", function (Eloquent\Builder $query) {
$query->where('term'...)
}
$cars->whereHas("finance", function (Eloquent\Builder $query) {
$query->where('payment'...)
}
Is there some way to aggregate the where(s) together without needing to do all the where calls within the containing whereHas?
The SQL query being executed:
SELECT id
FROM `cars`
WHERE EXISTS
(SELECT `finance`.`payment` as payment
FROM `finance`
INNER JOIN `car_finance` ON `finance`.`id` = `car_finance`.`finance_id`
WHERE `car_finance`.`car_id` = `cars`.`id`
AND `payment` >= 50)
AND EXISTS
(SELECT *
FROM `finance`
INNER JOIN `car_finance` ON `finance`.`id` = `car_finance`.`finance_id`
WHERE `car_finance`.`car_id` = `cars`.`id`
AND `payment` <= 200)
AND EXISTS
(SELECT *
FROM `finance`
INNER JOIN `car_finance` ON `finance`.`id` = `car_finance`.`finance_id`
WHERE `car_finance`.`car_id` = `cars`.`id`
AND `term` = 48)
AND EXISTS
(SELECT *
FROM `finance`
INNER JOIN `car_finance` ON `finance`.`id` = `car_finance`.`finance_id`
WHERE `car_finance`.`car_id` = `cars`.`id`
AND `deposit` = 1000)
AND `active` = 1
The SQL query that I would like to be executed:
SELECT *
FROM cars
WHERE EXISTS
(SELECT *
FROM `finance`
INNER JOIN `car_finance` ON `finance`.`id` = `car_finance`.`finance_id`
WHERE `car_finance`.`car_id` = `cars`.`id`
AND deposit = 1000
AND term = 48
AND payment >= 50
AND payment <= 200)
AND active = 1
Your question it's not clear but I think you want this:
$cars->whereHas("finance", function ($query) {
$query->where('deposit', 1000)->where('term', 48)
->whereBetween('payment', 50, 200);
})->where('active', 1)->get();

Count Performance optimisation

I got 2 versions of basically the same code. (See below) Version 1 is running at 2 seconds, version 2 is running at .5 - .6 seconds. There are 10 million rows currently from where I am selecting from, but this number goes up pretty fast. I would like to go even lower if possible. The problem is that I use Version 2, and I need to call that 30 times (different statuses, different usernames, etc), the final number is still going to be too big for what I need. Is there a 3rd version I could use instead? Or is there any other way I could make this to be even faster? Or the only thing that I could do is play with indexes.
Basically all these counts would be displayed in the most visited screen in a web application, and 30 * .5 seconds sounds a bit too much when 1000 users are using the system in the same time.
Version 1
declare #a1 datetime; set #a1 = GETDATE()
declare #int1 INT,#int2 INT,#int3 INT,#int4 INT,#int5 INT,#int6 INT,#int7 INT,#int8 INT
select #int1 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'a'
select #int2 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'b'
select #int3 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'c'
select #int4 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'd'
select #int5 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'e'
select #int6 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'f'
select #int7 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'g'
select #int8 = COUNT(Id) from ToDos where StatusId = 1 and stringUserId = 'h'
select #int1, #int2, #int3, #int4, #int5, #int6, #int7, #int8
SELECT DATEDIFF(MILLISECOND, #a1, GETDATE())
Version 2
declare #a1 datetime; set #a1 = GETDATE()
select stringUserId, count(stringUserId)
from ToDos
where StatusId = 1 and stringUserId in ('a','b','c','d','e','f','g','h')
group by stringUserId
order by COUNT(stringUserId) desc
SELECT DATEDIFF(MILLISECOND, #a1, GETDATE())
Try conditional count.
select
#int1 = COUNT(CASE WHEN stringUserId = 'a' THEN 1 END),
#int2 = COUNT(CASE WHEN stringUserId = 'b' THEN 1 END),
#int3 = COUNT(CASE WHEN stringUserId = 'c' THEN 1 END),
#int4 = COUNT(CASE WHEN stringUserId = 'd' THEN 1 END),
#int5 = COUNT(CASE WHEN stringUserId = 'e' THEN 1 END),
#int6 = COUNT(CASE WHEN stringUserId = 'f' THEN 1 END),
#int7 = COUNT(CASE WHEN stringUserId = 'g' THEN 1 END),
#int8 = COUNT(CASE WHEN stringUserId = 'h' THEN 1 END)
from ToDos
where StatusId = 1
FYI: I didnt include the ELSE part for CASE because for default will return NULL and COUNT doesnt count nulls
You could try:
select a.* from (select stringUserId, count(stringUserId) as IDCount
from ToDos
where StatusId = 1 and stringUserId in ('a','b','c','d','e','f','g','h')
group by stringUserId) a
order by a.IDCount desc
that eliminates the count function from the order by

GROUP BY and HAVING in linq

I want to convert this code to linq:
select t1.title, COUNT(*)as num
from t1 INNER join t2 on t2.gId = t1.Id
group by t1.title, t1.cId
having t1.cId = 2
I tried this below code:
from p in db.t1s join r in db.t2s on p.Id equals r.gId
where p.cId == 2
group p by p.title into g
select new{ name = from o in g select o.title, num = g.Count()}
But this doesn't return COUNT correctly.
please guide me how can I solve the problem
thanks
Without sample data its hard to get it right, but try this snippet
from p in db.t1s
join r in db.t2s on p.Id equals r.gId
where p.cId == 2
group p by new {p.title, p.cId} into grouped
select new{ name = grouped.Key.title, num = grouped.Count()}
Also, note that this sql:
select t1.title, COUNT(*)as num
from t1 INNER join t2 on t2.gId = t1.Id
group by t1.title, t1.cId
having t1.cId = 2
Will always return 1 as result of COUNT(*). The reason is that you have filtering t1.cId = 2 and grouping by t1.cId as second parameter.

Resources