Strange PDO MySQL Problem - php

I am trying to perform a query in a PHP script. The query works fine in my MySQL client however it does not seem to working within my code. I am using PDO. I am thinking it might have limitations, because it seems to work fine with a less complicated query.
Here is the query:
SELECT D.status, D.createdBy, D.createDate, D.modifiedBy, D.modifiedDate,D.IPAddress, D.adminStatus, D.campus, D.buildingID, D.deviceShortName, D.distributionID, D.networkKey, D.deviceName, D.test, D.pkDevices, D.DNSRule, D.Domain, D.DNSOverride, D.noDNS, D.pkModel, DM.Model, DM.pkManufacturer, M.manufacturer FROM Devices AS D INNER JOIN DeviceModel AS DM ON D.pkModel = DM.pkModel INNER JOIN Manufacturer AS M ON DM.pkManufacturer = M.pkManufacturer WHERE D.status = '1' AND D.adminStatus = 'Active' ORDER BY D.deviceName
Here is where I am trying to call it in my script:
$dbhDevices = newPDO('mysql:host='.$_SESSION['OpsDBServer'].'.ops.tns.its.psu.edu;dbname='.$_SESSION['OpsDB'], $_SESSION['yoM'], $_SESSION['aMa']);
$sqlDevices = "SELECT D.status, D.createdBy, D.createDate, D.modifiedBy,
D.modifiedDate, D.IPAddress, D.adminStatus, D.campus, D.buildingID,
D.deviceShortName, D.distributionID, D.networkKey, D.deviceName, D.test,
D.pkDevices, D.DNSRule, D.Domain, D.DNSOverride, D.noDNS, D.pkModel, DM.Model,
DM.pkManufacturer, M.manufacturer
FROM Devices AS D
INNER JOIN DeviceModel AS DM ON D.pkModel = DM.pkModel
INNER JOIN Manufacturer AS M ON DM.pkManufacturer = M.pkManufacturer
WHERE D.status = '1' AND D.adminStatus = 'Active' ORDER BY D.deviceName";
foreach ($dbhDevices->query($sqlDevices) as $rowDevices)
{
Again, the query does work with the MySQL client.

try enabling errors if haven't done already:
error_reporting(E_ALL);
$dbhDevices->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

In the older versions of PDO usage you have to "initialize" your PDO variable when you declare it for some reason. Try putting a line before this code that generically initializes $dbhDevices and see if that does the trick. I have my doubts because you say it works fine with less complicated queries but it's worth a try.

I got it working by using a LEFT JOIN instead of an INNER JOIN. Strange, but it is working.

Related

Mysql query taking long time even with LIMITS

1. Summarise the problem
Our company has been using this system for a long time and people feel huge system slowdown. I can't rewrite code because its super hardcoded and too many files to do so.
Few months ago we saw that one query takes about 170 s to execute.
My workaround was add LIMITS to each query and from 170s it went down to 2-3s. But last week i saw that code now takes about 5-25 sec.
Also this system is on php 5.2. Its basically impossible to upgrade code to work for 5.6
3 people was rewriting this code and after 8 hour we managed to make to login page.
Indexing is limited because most of database info have strings rather than integer.
2. Provide background including what you've already tried
What i tried:
- Adding limits by default 300, also users can change this limit.
- Migrating server to better hardware.
- Giving more RAM (10gb now) and two virtual CPU.
- Migrating from local storage to network (better performance at this moment).
3. Show some code
SELECT pastabos_apskaitininkui,
uzdaviniai.pakr_salis,
uzdaviniai.iskr_salis,
uzdaviniai.id AS uzdavinio_id,
salys.salis AS muitines_salis,
uzdaviniai.pakr_regionas,
uzdaviniai.iskr_regionas,
uzdaviniai.pakr_miestas,
uzdaviniai.iskr_miestas,
uzdavinio_priekaba,
priekabos.tipas AS priekabos_tipas,
uzdaviniai.kas_sukure_skyrius,
uzdaviniai.kam_sukure_skyrius,
uzdaviniai.kas_sukure_vadyb,
uzdaviniai.kam_sukure_vadyb,
uzdav_users.vardas_sutr AS uzdav_user_vardas,
pakrov_salis.sutrumpinimas AS uzdav_pakr_salis,
iskrov_salis.sutrumpinimas AS uzdav_iskr_salis,
uzdaviniai.pasikrovimo_data AS uzd_pasikrovimo_data,
uzdaviniai.pristatymo_data AS uzd_pristatymo_data,
uzdaviniai.pastabos,
suma_vykdytojui_valiuta,
vykdytojui_valiuta,
uzdaviniai.eil_nr,
uzdaviniai.statusas,
uzdaviniai.statusas_baigtas_ranka,
keliones_lapas.reiso_nr,
keliones_lapas.masina,
keliones_lapas.masinos_id,
keliones_lapas.priekabos_nr,
keliones_lapas.priekabos_id,
keliones_lapas.priekabos2_nr,
keliones_lapas.reiso_pavadinimas,
keliones_lapas.vykdytojo_tipas,
keliones_lapas.vykdytojo_imone,
keliones_lapas.atvykimo_data,
keliones_lapas.vairuotojas,
keliones_lapas.vairuotojas2,
keliones_lapas.vairuotojas3,
keliones_lapas.vairuotojas4,
keliones_lapas.marsrutas,
klientai.firmos_pavadinimas AS uzsakovas,
uzsakovo_uzs_nr,
valiutos.valiuta AS frachto_valiuta,
uzsakymas.vadybininkas,
uzsakymas.skyrius,
uzsakymas.frachtas_suma,
uzsakymas.pavadinimas,
uzsakymas.uzsakymo_id,
uzsakymas.reg_data,
uzsakymas.pastabos AS uzs_pastabos,
uzsakymas.statusas AS uzsakymo_statusas,
sask_ist.serija,
sask_ist.sask_nr,
sask_ist.id AS sask_id,
sask_ist.suma,
sask_ist.valiuta,
sask_ist.kursas AS sask_ist_kursas,
sask_ist.apmoketi_iki,
sask_ist.atidejimas,
issiuntimo_data,
sask_ist_apmokejimas.suma AS ist_apm_suma,
sask_ist_apmokejimas.valiuta AS ist_apm_valiuta,
sask_ist_apmokejimas.kursas AS ist_apm_kursas,
sask_ist_apmokejimas.id AS ist_apm_id,
klientu_pakr_vietos.pavadinimas AS muitines_pavadinimas,
klientu_pakr_vietos.miestas AS muitines_miestas,
klientu_pakr_vietos.adresas AS muitines_adresas,
kokio_krovinio_dalis,
krovinys_konsoliduotas,
kroviniu_tipai.pavadinimas AS krovinio_pavadinimas,
kroviniai.pasikrovimo_data,
kroviniai.pristatymo_data,
kroviniai.uzsakovo_krovinio_nr,
kroviniai.id AS krovinio_id,
svoris_t,
ldm,
turis,
paleciu_skaicius,
vnt,
temperature,
kroviniai.konteinerio_nr,
kroviniai.pakr_vietos_id AS kr_pakr_vietos_id,
kroviniai.iskr_vietos_id AS kr_iskr_vietos_id,
kroviniai.pakr_salis AS kr_pakr_salis,
kroviniai.iskr_salis AS kr_iskr_salis,
kroviniai.pakr_miestas AS kr_pakr_miestas,
kroviniai.pakr_regionas AS kr_pakr_regionas,
kroviniai.iskr_regionas AS kr_iskr_regionas,
kroviniai.iskr_miestas AS kr_iskr_miestas,
kroviniai.ismuitinimo_data AS ismuitinimo_data,
kroviniai.uzmuitinimo_data AS uzmuitinimo_data,
kroviniai.pasienio_postas AS pasienio_postas,
kroviniai.ismuitinimo_vieta AS ismuitinimo_vieta,
statusai.pavadinimas AS st_pavadinimas,
st_uzsakymai.id AS st_id,
st_salys.salis AS st_salis,
st_uzsakymai.data AS st_data,
st_uzsakymai.laikas AS st_laikas,
st_uzsakymai.ivykio_pastabos_sutr AS st_pastabos_sutr,
st_uzsakymai.ivykio_pastabos AS st_pastabos,
st_keliones_lapas.reiso_pavadinimas AS st_reiso_pav,
vairuotojai.vardas AS sq_vardas,
priekabos.masinos_nr AS sq_priekaba
FROM uzdaviniai
LEFT JOIN priekabos
ON priekabos.id = uzdaviniai.uzdavinio_priekaba
LEFT JOIN users AS uzdav_users
ON uzdav_users.id = uzdaviniai.kam_sukure_vadyb
LEFT JOIN salys AS pakrov_salis
ON pakrov_salis.id = uzdaviniai.pakr_salis
LEFT JOIN salys AS iskrov_salis
ON iskrov_salis.id = uzdaviniai.iskr_salis
LEFT JOIN uzsakymas
ON uzdaviniai.uzsakymo_id = uzsakymas.uzsakymo_id
LEFT JOIN uzd_kur_vykdytas
ON uzdaviniai.id = uzd_kur_vykdytas.uzdavinio_id
LEFT JOIN keliones_lapas
ON keliones_lapas.reiso_nr = uzd_kur_vykdytas.reiso_nr
LEFT JOIN st_uzsakymai
ON st_uzsakymai.uzdavinio_id = uzdaviniai.id
LEFT JOIN statusai
ON statusai.id = st_uzsakymai.statuso_id
LEFT JOIN salys AS st_salys
ON st_salys.id = st_uzsakymai.salis
LEFT JOIN keliones_lapas AS st_keliones_lapas
ON st_keliones_lapas.reiso_nr = st_uzsakymai.reiso_nr
LEFT JOIN vairuotojai
ON vairuotojai.id = keliones_lapas.vairuotojas
LEFT JOIN sask_ist_uz_ka
ON sask_ist_uz_ka.uzsakymo_id = uzsakymas.uzsakymo_id
LEFT JOIN sask_ist
ON sask_ist.id = sask_ist_uz_ka.sask_id
LEFT JOIN sask_ist_apmokejimas
ON sask_ist.id = sask_ist_apmokejimas.sask_id
LEFT JOIN uzsakymo_kroviniai
ON uzsakymas.uzsakymo_id = uzsakymo_kroviniai.uzsakymo_id
LEFT JOIN kroviniai
ON kroviniai.id = uzsakymo_kroviniai.krovinio_id
LEFT JOIN klientu_pakr_vietos
ON klientu_pakr_vietos.id = kroviniai.ismuitinimo_vieta
LEFT JOIN klientu_pakr_vietos AS iskr_vietos_uzd
ON iskr_vietos_uzd.id = uzdaviniai.pakr_vietos_id
LEFT JOIN salys
ON salys.id = klientu_pakr_vietos.salis
LEFT JOIN cmr_kroviniai
ON kroviniai.id = cmr_kroviniai.krovinio_id
LEFT JOIN cmr
ON cmr.id = cmr_kroviniai.cmr_id
LEFT JOIN cmr_panaudojimas
ON cmr_panaudojimas.cmr_id = cmr_kroviniai.cmr_id
AND keliones_lapas.reiso_nr = cmr_panaudojimas.reiso_nr
LEFT JOIN kroviniu_tipai
ON kroviniu_tipai.id = kroviniai.krovinio_pavadinimas
LEFT JOIN klientai
ON klientai.id = uzsakymas.kliento_id
LEFT JOIN valiutos
ON valiutos.id = uzsakymas.frachtas_valiuta
WHERE 1 = 1
AND ( `uzdaviniai`.`pasikrovimo_data` BETWEEN
'2019-07-08' AND '2019-07-08 23:59:59'
)
ORDER BY uzdaviniai.pasikrovimo_data DESC
LIMIT 300
As you can see there is many left join, statements.
4. Result
What i want is some help what can i do with this piece of crap or some recommendation what can i change. As i expect these query will take more and more time to execute.
If the query is fast when executed directly in mysql console, then the query has no problem at all, and what is slow is the php code that uses the results of the query, php code that you don't show and that you should revise/post here.
If the query is slow even in mysql console, then the problem can be the size of the master/joined tables (but this may be resolved by relaxing the memory limits of the mysql server and/or adding ram to the server), or could be non correct indexing of the joined tables, since any LEFT JOIN needs the joined table to be indexed on the field you use to join it (and this could be resolved by creating the correct indexes on the joined tables).
Consider changing your
WHERE 1 = 1
AND ( `uzdaviniai`.`pasikrovimo_data` BETWEEN
'2019-07-08' AND '2019-07-08 23:59:59'
)
TO
WHERE uzdaviniai.pasikrovimo_data BETWEEN
'2019-07-08' AND '2019-07-08 23:59:59'
and let us know results (with the backticks), please.

Equivalent expression to MySql Left Join

I'm working on my website and I'm stuck on writing MySQL query which uses "LEFT JOIN" syntax. A simple example of my query is shown bellow:
SELECT p.surname, f.f_path as players_image
FROM player p LEFT JOIN file f ON p.id_image = f.id_file
The problem is that I'm actually using 8 different tables to get necessary data and I'm joining them after WHERE clause(I found it more easier to do that way):
SELECT p.surname, f.f_path as players_image
FROM player, file
WHERE p.id_image = f.id_file
Can I somehow modify the second queries WHERE clause to get the same result as the first query returns?
I know that Oracle DB uses syntax like WHERE p.id_image(+) = f.id_file to manage that. It tried that on MySQL data base but it gave me an error.
The original SQL query(table names are different):
SELECT sp.id_speletajs, sp.vards, sp.uzvards, ss.numurs, f.f_path as attels, k.id_komanda, p.nosaukums as pozicija
FROM speletajs sp, fails f, speletaja_statistika ss, cempionata_komanda ck, komanda k, cempionats c, sezona s, pozicija p
WHERE
sp.id_attels = f.id_fails
and sp.id_speletajs = ss.id_speletajs
and ss.id_cempionata_komanda = ck.id_cempionata_komanda
and ss.id_pozicija = p.id_pozicija
and ck.id_komanda = k.id_komanda
and ck.id_cempionats = c.id_cempionats
and c.id_sezona = s.id_sezona
and k.mana_komanda = true
and s.nosaukums = (select max(s1.nosaukums) from sezona s1)

codeigniter, Using Case When for Where Query

I have this query which i want to make it work in codeigniter query form, so want to know if its possible or not.
This is the query i want to implement in Codeigniter in codeigniter's own way.
use zorkif_next;
SELECT
`osp_job_status_track`.`StatusID`,
`osp_job_status_track`.`SubStatusID`,
`osp_job_sub_status`.`CurrentStatus`
FROM
(`osp_job_details`)
LEFT JOIN
`osp_job_status_track` ON `osp_job_status_track`.`JobID` = `osp_job_details`.`JobID`
LEFT JOIN
`osp_job_status` ON `osp_job_status`.`StatusID` = `osp_job_status_track`.`StatusID`
LEFT JOIN
`osp_job_sub_status` ON `osp_job_sub_status`.`SubStatusID` = `osp_job_status_track`.`SubStatusID`
LEFT JOIN
`hr_employee_details` ON `hr_employee_details`.`EmployeeID` = `osp_job_details`.`AssignToEmployeeID`
LEFT JOIN
`osp_job_type` ON `osp_job_type`.`JobTypeID` = `osp_job_details`.`JobtypeID`
WHERE
-- `isDefault` = 1
-- AND
CASE WHEN `osp_job_status`.`StatusID` = 2
THEN `osp_job_sub_status`.`CurrentStatus` = 3
ELSE `osp_job_status`.`StatusID` >= 2
END ;
So how to implement this query in
$this->db->where($where);
???
It is not possible in CI.You need to write your own query. Please have a look on this file.You can see all the available methods there.
\system\database\DB_active_rec.php

Complex SQL query into Zend

I am trying to build a social network using Zend Framework. However, recently I have difficulty in making some complex SQL queries into Zend language. For example:
"SELECT t.plural_name, p.name as users_name, u.ID
FROM users u, profile p, relationships r, relationship_types t
WHERE t.ID=r.type
AND r.accepted=1
AND (r.usera={$user} OR r.userb={$user})
AND IF( r.usera={$user},u.ID=r.userb,u.ID=r.usera)
AND p.user_id=u.ID"
How could I execute this query using Zend's select() object? Thank you very much!
Whenever I have complex queries to deal with, I usually try to run them in MySQL. Once I have found the exact SQL statement, I start to 'translate' it to Zend. I seems a bit complex but in the long run, you get to do them in Zend right away. Here is how I break it down.
First figure out what the SQL statement is:
SELECT t.plural_name, p.name as users_name, u.ID
FROM users u, profile p, relationships r, relationship_types t
WHERE t.ID=r.type AND r.accepted=1 AND
(r.usera={$user} OR r.userb={$user}) AND
IF( r.usera={$user},u.ID=r.userb,u.ID=r.usera) AND
p.user_id=u.ID
Now, you will want to convert all the relationships to joins. The joins are somewhat scary at the beginning but it's simply a way to put the table and the criteria on which it joins to another table in one line.
SELECT t.plural_name, p.name AS users_name, u.ID
FROM users u
INNER JOIN profile AS p ON p.user_id = u.ID
INNER JOIN relationships AS r ON IF(r.usera={$user}, u.ID=r.userb, u.ID=r.usera)
INNER JOIN relationship_types AS t ON t.ID = r.type
WHERE
(r.usera={$user} OR r.userb={$user}) AND
r.accepted=1
Now that it is written in a more 'Zend friendly' way, you can easily start to convert it to Zend:
$select = $this->select()->setIntegrityCheck(false);
$select->from(array('u'=>'users'), '');
$select->join(array('p'=>'profile'), 'p.user_id = u.ID', '');
$select->join(array('r'=>'relationships'), 'IF(r.usera={$user}, u.ID=r.userb, u.ID=r.usera)', '');
$select->join(array('t'=>'relationship_types'), 't.ID = r.type', '');
$select->columns(array(
't.plural_name',
'users_name'=>'p.name',
'u.ID'));
$select->where('r.usera={$user}');
$select->orWhere('r.userb={$user}');
$select->where('r.accepted=1');
And that should do the job.
You can take this as example:(though its not complete)
<?php
$this->_query = $this->_DB->select()->from(array('u'=>'users'),array('(u.ID)'))
->join(array('p'=>'profile'),
'p.user_id = u.ID',
'p.name AS users_name')
->join(array('r'=>'relationships'),
'r.userb = u.ID')
->join(array('t'=>'relationship_types'),
't.ID = r.type',
't.plural_name')
->where('t.ID = r.type AND r.accepted = 1')
->where('r.usera = :user')
->orWhere('r.userb = :user')
->bind(array('user'=>$user));
For really complex queries it might be easier just to use SQL. It is only important that all parameters going into the query are properly escaped to prevent SQL injections.

Slow query - Multiple joins and a lot of data

I'm sure there is a better way I could be doing this. I have three main tables with large amounts of data to run through:
records_main, sales, and appointments. Each with close to 20,000 records.
I need to join these three tables as well as a few others that arn't two large.
$SQL = "SELECT DISTINCT appointments.id AS aid, appointments.date, appointments.estimate_price, appointments.next_action, appointments.next_action_date, appointments.result, appointments.result_type, appointments.notes,
customer.id AS cid, customer.homeowner1_fname, customer.homeowner1_lname, customer.address, customer.city, customer.state, customer.zipcode, customer.phone1, customer.phone1_type, customer.phone2, customer.phone2_type, customer.phone3, customer.phone3_type, customer.phone4, customer.phone4_type, customer.phone5, customer.phone5_type, customer.lead_source, customer.lead_category, customer.primary_interest, customer.secondary_interest, customer.additional_interest1, customer.additional_interest2,
originator.employee_id AS originator_employee_id,originator.fname AS originator_fname,originator.lname AS originator_lname,
setter.employee_id AS setter_employee_id,setter.fname AS setter_fname,setter.lname AS setter_lname,
resetter.employee_id AS resetter_employee_id, resetter.fname AS resetter_fname, resetter.lname AS resetter_lname,
salesrep.employee_id AS salesrep_employee_id, salesrep.fname AS salesrep_fname, salesrep.lname AS salesrep_lname,
salesrep2.employee_id AS salesrep2_employee_id, salesrep2.fname AS salesrep2_fname, salesrep2.lname AS salesrep2_lname
FROM
core_records_appointments as appointments
INNER JOIN core_records_main as customer ON appointments.customer = customer.id
LEFT JOIN core_employees_main as originator ON appointments.originator = originator.id
LEFT JOIN core_employees_main as setter ON appointments.setter = setter.id
LEFT JOIN core_employees_main as resetter ON appointments.resetter = resetter.id
LEFT JOIN core_employees_main as salesrep ON appointments.sales_representative = salesrep.id
LEFT JOIN core_employees_main as salesrep2 ON appointments.sales_representative2 = salesrep2.id
";
This takes a few seconds but finally does load. The last join I put though seems to break the query together:
LEFT JOIN core_records_sales as sales ON appointments.day = sales.day_sold AND appointments.customer = sales.customer
After this I have a limit set and a group by
Anything I can do to improve this? I am using this with jqgrid, not sure if that helps
As a first approach, try to execute the query on the database using the EXPLAIN syntax. This will give you an analysis of the statement and tells you, if it uses indexes at all. If it doesn't use indexes or not enough indexes, try adding them to the tables.
Have you tried giving index on all the columns you are LEFT JOINing on?
TRY giving index to all these if they are not already declared as index

Categories