Laravel run complex query without disabling mysql strict mode - laravel

I have quite a complex query which is like:
SELECT
COALESCE (
SUM (
CASE WHEN `closed_job_reports`.`job_report_id` IS NOT NULL THEN 1 ELSE 0 END
),
0
) AS `CLOSED`,
COALESCE (
SUM (
CASE WHEN `job_reports`.`id` IS NULL
AND `jobs`.`deadline` <= CURRENT_TIMESTAMP() THEN 1 ELSE 0 END
),
0
) AS `OVERDUE`,
COALESCE (
SUM (
CASE WHEN (
`assigned_jobs`.`assigned_job_id` IS NULL
AND `pending_jobs`.`id` IS NOT NULL
AND `jobs`.`deadline` > NOW ()
)
OR (
`assigned_jobs`.`assigned_job_id` IS NOT NULL
AND `jobs`.`deadline` > NOW ()
AND `job_reports`.`id` IS NULL
) THEN 1 ELSE 0 END
),
0
) AS `PENDING`,
COALESCE (
SUM (
CASE WHEN `closed_job_reports`.`job_report_id` IS NULL
AND `job_reports`.`id` IS NOT NULL THEN 1 ELSE 0 END
),
0
) AS `AWAITING_CLOSURE`,
COALESCE (
SUM (
CASE WHEN (
`job_reports`.`id` IS NULL
OR `assigned_jobs`.`assigned_job_id` IS NULL
)
AND (
`jobs`.`deadline` > NOW ()
) THEN 1 ELSE 0 END
),
0
) AS `OPEN`,
COALESCE (
COUNT (*),
0
) AS `TOTAL`,
COALESCE (
SUM (
`job_reports`.`distance_travelled`
),
0
) AS `distance_travelled`,
COALESCE (
ROUND(
SUM (
CASE WHEN (
`job_reports`.`id` IS NOT NULL
AND `jobs`.`job_category_id` = 2
) THEN ABS (
TIMESTAMPDIFF (
SECOND, `job_reports`.`end_time`,
`job_reports`.`start_time`
)
) ELSE 0 END
) / 3600,
2
),
0
) AS `hours_worked`,
COALESCE (
COUNT (`job_reports`.`id`),
0
) AS `num_reported_sites`,
COALESCE (
SUM (
CASE WHEN `jobs`.`job_category_id` = 2
AND `job_reports`.`id` IS NOT NULL THEN 1 ELSE 0 END
),
0
) AS `pm_num_reported_jobs`,
COALESCE (
SUM (
CASE WHEN `jobs`.`job_category_id` = 2 THEN 1 ELSE 0 END
),
0
) AS `pm_num_jobs`
FROM
`jobs`
INNER JOIN `job_categories` ON `job_categories`.`id` = `jobs`.`job_category_id`
LEFT OUTER JOIN `assigned_jobs` ON `jobs`.`id` = `assigned_jobs`.`job_id`
LEFT OUTER JOIN `job_reports` ON `assigned_jobs`.`assigned_job_id` = `job_reports`.`assigned_job_id`
LEFT OUTER JOIN `closed_job_reports` ON `job_reports`.`id` = `closed_job_reports`.`job_report_id`
LEFT OUTER JOIN `pending_jobs` ON `jobs`.`id` = `pending_jobs`.`new_job_id`
WHERE
`jobs`.`date_added` BETWEEN '2022-01-01' AND '2022-02-17'
-- GROUP BY
-- `closed_job_reports`.`job_report_id`, `job_reports`.`id`, `assigned_jobs`.`assigned_job_id`, `pending_jobs`.`id`, `closed_job_reports`.`job_report_id`, `job_reports`.`id`, `assigned_jobs`.`assigned_job_id`
ORDER BY
`jobs`.`id` DESC
I can easily run it from PhpMyAdmin and get what I want like what is shown below:
but when running from laravel with the DB::select method, I get a syntax error:
SQLSTATE[42000]: Syntax error or access violation: 1140 Mixing of
GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is
illegal if there is no GROUP BY clause (SQL: SELECT
...
I have a lot of such queries that I would be running. I checked this post:
Syntax error or access violation: 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...)
but mine seems to be a little more complicated owing to the fact that I have to query from several related tables. I have seen other people recommend disabling mysql strict mode, but I don't want to do that.
I know some of you might have encountered this issue with complicated queries. Please what steps or techniques you use in resolving some of these issues? Thanks.

Okay. so you've got a really complex query like mine? Well, I found out I did not need a view from the database because it was unnecessary in my case.
First, I had to break down my query into smaller parts and one at a time. This was after I was pointed to the Laravel docs https://laravel.com/docs/9.x/queries#raw-expressions
I started with the main table from the original query - jobs and proceeded to adding the joins to the query.
The grouping of the data was the most complicated part. That was what I had problems with. So after breaking down the query, I had to change what I was using for the original grouping of data. Grouping the data into job category name (or job category id) made it simpler.
In the end, the displayed results I was getting looked much better.
Here is a code to illustrate.
I have made some modifications to the original queries but still maintaining the joins that I needed.
$users = DB::table('jobs')
->select(DB::raw(
'job_categories.category_name, COUNT(jobs.id) as jobs_count, COUNT(assigned_jobs.assigned_job_id) AS assigned_jobs_count,
COUNT(recurring_jobs.job_id) AS recurring_jobs_count,
COALESCE(SUM(
CASE WHEN
assigned_jobs.assigned_job_id IS NULL
THEN 1 ELSE 0
END
), 0) AS unassigned_jobs_count,
COUNT(job_reports.id) AS reported_jobs_count,
COALESCE(SUM(
CASE WHEN job_reports.id IS NULL
THEN 1 ELSE 0
END
), 0) AS unreported_jobs_count,
COALESCE(SUM(
CASE WHEN closed_job_reports.job_report_id IS NOT NULL THEN 1 ELSE 0
END
), 0) AS closed_jobs_count,
COALESCE(SUM(
CASE WHEN job_reports.id IS NOT NULL AND closed_job_reports.job_report_id IS NULL THEN 1 ELSE 0
END
), 0) AS reported_unclosed_jobs_count,
COALESCE(SUM(
CASE WHEN
(job_reports.id IS NULL AND jobs.deadline > NOW() AND assigned_jobs.assigned_job_id IS NULL)
THEN 1 ELSE 0
END
), 0) AS opened_only_jobs_count,
COALESCE(SUM(
CASE WHEN
job_reports.id IS NULL AND jobs.deadline > NOW() AND assigned_jobs.assigned_job_id IS NOT NULL OR
(job_reports.id IS NULL AND jobs.deadline > NOW() AND pending_jobs.id IS NOT NULL)
THEN 1 ELSE 0
END
),0) AS pending_jobs_count,
COALESCE(SUM(
CASE WHEN job_reports.id IS NULL AND jobs.deadline <= NOW() THEN 1 ELSE 0
END
), 0) AS overdue_jobs_count
'
))
->groupBy('job_categories.category_name')
->join('job_categories', 'job_categories.id', '=', 'jobs.job_category_id')
->leftJoin('assigned_jobs', 'jobs.id', '=', 'assigned_jobs.job_id')
->leftJoin('pending_jobs', 'jobs.id', '=', 'pending_jobs.new_job_id')
->leftJoin('job_reports', 'job_reports.assigned_job_id', '=', 'assigned_jobs.assigned_job_id')
->leftJoin('closed_job_reports', 'closed_job_reports.job_report_id', '=', 'job_reports.id')
->leftJoin('recurring_jobs', 'recurring_jobs.job_id', '=', 'jobs.id')
->get();
I hope this helps someone to troubleshoot their issues with the error
SQLSTATE[42000]: Syntax error or access violation: 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
when using laravel or other similar framework...

Related

Oracle: Value from main query is not available in subquery

I have this query, and one of its column is a subquery that should be bringing a list of values using a listagg function. This list has its starting point as the S.ID_ORGAO_INTELIGENCIA value. The list is a should be, it always has values.
The listagg function is consuming an inline view that uses a window function to create the list.
select *
from (
SELECT DISTINCT S.ID_SOLICITACAO,
S.NR_PROTOCOLO_SOLICITACAO,
S.DH_INCLUSAO,
S.ID_USUARIO,
U.NR_CPF,
OI.ID_MODULO,
OI.ID_ORGAO_INTELIGENCIA,
OI.NO_ORGAO_INTELIGENCIA,
R.ID_ATRIBUICAO,
P.ID_PERMISSAO,
1 AS TIPO_NOTIFICACAO,
(
select LISTAGG(oc6.ID_ORGAO_INTELIGENCIA || '-' || oc6.ord || '-', '; ') WITHIN GROUP (ORDER BY oc6.ord) eai
from (
SELECT oc1.ID_ORGAO_INTELIGENCIA,
oc1.ID_ORGAO_INTELIGENCIA_PAI,
oc1.SG_ORGAO_INTELIGENCIA,
rownum as ord
FROM TB_ORGAO_INTERNO oc1
WHERE oc1.DH_EXCLUSAO is null
-- THE VALUE FROM S.ID_ORGAO_INTELIGENCIA IS NOT AVAILBLE HERE
START WITH oc1.ID_ORGAO_INTELIGENCIA = S.ID_ORGAO_INTELIGENCIA
CONNECT BY prior oc1.ID_ORGAO_INTELIGENCIA_PAI = oc1.ID_ORGAO_INTELIGENCIA
) oc6) aproPrec
FROM TB_SOLICITACAO S
INNER JOIN TB_ORGAO_INTERNO OI ON S.ID_ORGAO_INTELIGENCIA = OI.ID_ORGAO_INTELIGENCIA
INNER JOIN TB_RELACIONAMENTO_ATRIBUICAO R
ON (R.ID_MODULO = OI.ID_MODULO AND R.ID_ORGAO_INTELIGENCIA IS NULL AND
R.ID_SOLICITACAO IS NULL)
INNER JOIN TB_PERMISSAO P
ON (P.ID_USUARIO = :usuario AND P.ID_ORGAO_INTELIGENCIA = :orgao AND
P.ID_ATRIBUICAO = R.ID_ATRIBUICAO)
INNER JOIN TB_USUARIO U ON (U.ID_USUARIO = S.ID_USUARIO)
WHERE 1 = 1
AND U.DH_EXCLUSAO IS NULL
AND P.DH_EXCLUSAO IS NULL
AND S.DH_EXCLUSAO IS NULL
AND OI.DH_EXCLUSAO IS NULL
AND R.ID_ATRIBUICAO IN :atribuicoes
AND P.ID_STATUS_PERMISSAO = 7
AND OI.ID_MODULO = 1
AND S.ID_STATUS_SOLICITACAO IN (1, 2, 5, 6)
and s.ID_ORGAO_INTELIGENCIA in (SELECT DISTINCT o.ID_ORGAO_INTELIGENCIA
FROM TB_ORGAO_INTERNO o
WHERE o.DH_EXCLUSAO IS NULL
START WITH o.ID_ORGAO_INTELIGENCIA = 3
CONNECT BY PRIOR o.ID_ORGAO_INTELIGENCIA = o.ID_ORGAO_INTELIGENCIA_PAI)
);
The problem is that the aproPrec column is always returning null as its result.
If I force the criteria to have the S.ID_ORGAO_INTELIGENCIA hardcoded, the list returns its true value.
If I chance this:
START WITH oc1.ID_ORGAO_INTELIGENCIA = S.ID_ORGAO_INTELIGENCIA
To this:
START WITH oc1.ID_ORGAO_INTELIGENCIA = 311
where 311 is the value that the S.ID_ORGAO_INTELIGENCIA column really has.
Is there a way to make this query works as 'I think' it should work?
To make it work, I changed the subquery by this another one:
(
select qt_.*
from (
SELECT QRY_NAME.*,
rownum as ord
FROM (
SELECT oc1.ID_ORGAO_INTELIGENCIA,
oc1.ID_ORGAO_INTELIGENCIA_PAI,
connect_by_root (oc1.ID_ORGAO_INTELIGENCIA) as root
FROM TB_ORGAO_INTERNO oc1
CONNECT BY NOCYCLE PRIOR oc1.ID_ORGAO_INTELIGENCIA_PAI = oc1.ID_ORGAO_INTELIGENCIA
) QRY_NAME
WHERE root = s.ID_ORGAO_INTELIGENCIA
) qt_
)

ORA-00920: Invalid relational operator (no missing/extra parenthesis)

I have an error when I try to execute the following query and I don't understand why.
SELECT DISTINCT lpad(obj.no, 4, '0') || ' - ' || obj.nom, obj.no
FROM TABLE(objects_pkg.get_all()) obj
WHERE obj.start_date <=
(CASE
WHEN util_pkg.is_date_valid(p_date => :v_start_date) ̲T̲H̲E̲N
to_date(:v_start_date, 'YYYY-MM-DD')
ELSE
trunc(SYSDATE)
END)
I checked for missing / extra parenthesis but I couldn't find any.
I tried several ways of structuring the CASE like the following but none of them worked.
SELECT DISTINCT lpad(obj.no, 4, '0') || ' - ' || obj.nom, obj.no
FROM TABLE(objects_pkg.get_all()) obj
WHERE (CASE
WHEN util_pkg.is_date_valid(p_date => :v_start_date) ̲T̲H̲E̲N
CASE WHEN obj.start_date <= to_date(:v_start_date, 'YYYY-MM-DD') THEN 1 ELSE 0 END
ELSE
CASE WHEN obj.start_date <= trunc(SYSDATE) THEN 1 ELSE 0 END
END) = 1
The error is always the same and is always triggered on the first T̲H̲E̲N̲ keyword of the first WHEN. I tried with and without the parenthesis, I tried to remove the THEN keyword and I tried a lot of things but nothing worked. The error is: ORA-00920: Invalid relational operator
I've also tried to change the entire where clause to the following but it didn't help.
SELECT DISTINCT lpad(obj.no, 4, '0') || ' - ' || obj.nom, obj.no
FROM TABLE(objects_pkg.get_all()) obj
WHERE (
(
TRIM(:v_start_date) ̲I̲S NULL
AND util_pkg.is_date_valid(p_date => :v_start_date)
AND obj.start_date <= to_date(:v_start_date, 'YYYY-MM-DD')
)
OR
(
(
:v_start_date IS NULL
OR NOT util_pkg.is_date_valid(p_date => :v_start_date)
)
AND obj.start_date <= trunc(SYSDATE)
)
)
For the above query, the error is triggered on the first I̲S̲ keyword within the WHERE clause (TRIM(:v_start_date) I̲S̲ NULL) but the error is still an ORA-00920.
Note: util_pkg.is_date_valid returns a BOOLEAN
I think your issue is that you are not testing the value from util_pkg.is_date_valid.
The WHEN part of the CASE statement needs to be tested against something.
CASE
WHEN util_pkg.is_date_valid(p_date => :v_start_date) >= ? ̲T̲H̲E̲N ...

How to create advanced check condition

I have an Oracle table and I would like to create a check condition like this :
ALTER TABLE MyTable
ADD CONSTRAINT MyTable_CHK2 CHECK (
case Dimension
When 1 then
nvl(dimensiontype1,-1)<>-1
when 2 then
nvl(dimensiontype1,-1)<>-1 and nvl(dimensiontype2,-1)<>-1
when 3 then
nvl(dimensiontype1,-1)<>-1 and nvl(dimensiontype2,-1)<>-1 and nvl(dimensiontype3,-1)<>-1
else
true
end
)
disable
The query is not working. I'm having the error : Missing Keyword.
Anyone know how to solve that please ?
Thanks.
You probably want an AND / OR expression
ALTER TABLE MyTable
ADD CONSTRAINT MyTable_CHK2 CHECK
(
( Dimension = 1 and nvl(dimensiontype1,-1) <> - 1 ) OR
( Dimension = 2 and (nvl(dimensiontype1,-1) <> - 1 and nvl(dimensiontype2,-1)<> -1 ) ) OR
( Dimension = 3 and (nvl(dimensiontype1,-1) <> -1 and nvl(dimensiontype2,-1)<> -1 and nvl(dimensiontype3,-1) <> -1))
) disable ;
Check constraint should be:
(dimension=1 and dimensiontype1 is not null)
or (dimension=2 and dimensiontype1 is not null and dimensiontype2 is not null)
or (dimension=3 and dimensiontyp1 is not null and dimensiontype2 is not null and dimensionType 3 is not null)

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)

remove rows from table having full outer join condition

I have used full outer join condition in my joining query for joining two tables and the sample code is as below
select * from(
select TO_CHAR(ROUND(col11)) as today1,TO_CHAR(ROUND(col12)) as today2 from T1
full outer join
select TO_CHAR(ROUND(col21)) as yes1,TO_CHAR(ROUND(col22)) as yes2 from T2
) MAIN
where MAIN.today1<>0 and MAIN.today2<>0 and MAIN.yes1<>0 and MAIN.yes2<>0
sample output expected as below
today1 today2 yes1 yes2
somevalue somevalue null null
null null some value somevalue
somevalue somevalue somevalue some value
0 0 0 0
I am trying to remove rows having all zero values using above where clause but output doubles and also row with zero values apperas. Can I know where I am going wrong. Any help much appreciated.
trying to remove rows having all zero values
use:
AND NOT ( MAIN.today1=0 and MAIN.today2=0 and MAIN.yes1=0 and MAIN.yes2=0 )
which can be transformed, using De Morgan's laws: ===> https://en.wikipedia.org/wiki/De_Morgan%27s_laws into:
AND ( NOT MAIN.today1=0 OR NOT MAIN.today2=0 OR NOT MAIN.yes1=0 OR NOT MAIN.yes2=0 )
which can be further simplified to:
AND ( MAIN.today1<>0 OR MAIN.today2<>0 OR MAIN.yes1<>0 OR MAIN.yes2<>0 )
Note: if you want to also get NULL values, you must use IS NULL operator:
where ( MAIN.today1<>0 OR MAIN.today1 IS NULL )
and ( MAIN.today2<>0 OR MAIN.today2 IS NULL )
and ( MAIN.yes1<>0 OR MAIN.yes1 IS NULL )
and ( MAIN.yes2<>0 OR MAIN.yes2 IS NULL )

Resources