I have a TABLE A called diagnoses . It has a disease_id and a visit_id. I am trying to return the diagnosis from TABLE A along with the disease name and visit details. I keep getting sql syntax errors. Is there a recommended way to push an objects to the array?
My code is
public function diagnosis_diseases(Disease $disease) {
$id = $disease->id;
$items = DB::select(DB::raw('SELECT * FROM diseases WHERE diseases.id = '.$id.' ;'));
foreach($items as $item){
$diagnosis = DB::select(DB::raw(' select * from diagnoses
where disease_id = '. $id.';' ));
$items->push($diagnosis);
}
dd($items);
}
You might need to use an inner join:
public function diagnosis_diseases(Disease $disease) {
$id = $disease->id;
$items = DB::select(DB::raw('SELECT * FROM diseases WHERE diseases.id = '.$id.' ;'));
foreach($items as $item){
$diagnosis = DB::select(DB::raw(' select * from diagnoses
inner join diseases on diagnoses.id = ' .$id' '));
$items->push($diagnosis);
}
dd($items);
}
I got a problem with condition in CakePHP 3. I'm trying to deal with deep associated models and build big queries for search engine.
here the query debbuged:
SELECT
Ouvrages.zone_id AS `Ouvrages__zone_id`,
Ouvrages.parent_id AS `Ouvrages__parent_id`,
Ouvrages.classe_ouvrage_id AS `Ouvrages__classe_ouvrage_id`,
Ouvrages.numero AS `Ouvrages__numero`,
Valeurs.valeur AS `Valeurs__valeur`
FROM
ouvrages Ouvrages
INNER JOIN
elements Elements
ON Ouvrages.id = (
Elements.ouvrage_id
)
INNER JOIN
valeurs Valeurs
ON Elements.id = (
Valeurs.element_id
)
INNER JOIN
caracteristiques Caracteristiques
ON Caracteristiques.id = (
Valeurs.caracteristique_id
)
WHERE
(
Ouvrages.zone_id in (
:c0,:c1,:c2,:c3,:c4,:c5,:c6,:c7,:c8,:c9,:c10,:c11
)
AND Ouvrages.classe_ouvrage_id = :c12
AND Elements.classe_element_id = :c13
AND Valeurs.caracteristique_id = :c14
AND valeur > :c15
)
GROUP BY
Valeurs.id
if i'm testing it in mysql console it works fine.
but cakephp's ORM doesn't give me the same result. With function gt lt gte or lte it doesn't work.
i used $this->log($query, 'debug') and configure my app config with new query log file but i got the same result if i have used debug:
SELECT
Ouvrages.zone_id AS `Ouvrages__zone_id`,
Ouvrages.parent_id AS `Ouvrages__parent_id`,
Ouvrages.classe_ouvrage_id AS `Ouvrages__classe_ouvrage_id`,
Ouvrages.numero AS `Ouvrages__numero`,
Valeurs.valeur AS `Valeurs__valeur`
FROM
ouvrages Ouvrages
INNER JOIN
elements Elements
ON Ouvrages.id = (
Elements.ouvrage_id
)
INNER JOIN
valeurs Valeurs
ON Elements.id = (
Valeurs.element_id
)
INNER JOIN
caracteristiques Caracteristiques
ON Caracteristiques.id = (
Valeurs.caracteristique_id
)
WHERE (
Ouvrages.zone_id in (
:c0,:c1,:c2,:c3
)
AND Ouvrages.classe_ouvrage_id = :c4
AND Elements.classe_element_id = :c5
AND Valeurs.caracteristique_id = :c6
AND valeur >= :c7)
GROUP BY
Valeurs.id
Thanks to ndm for explanation to debug sql query in AJAX. I configured my connection with log at true and i got this kind of result:
WHERE (
Ouvrages.zone_id in (
34,35,44,46
)
AND Ouvrages.classe_ouvrage_id = '60'
AND Elements.classe_element_id = '62'
AND Valeurs.caracteristique_id = '25'
AND valeur >= '5')
I'm trying to cast those numbers, but i didn't found how yet. A simply (int) doesn't work.
I understood my mistake. Actually we build a weird Valeurs table with a column value which is associated to a caracteristic. This value column is defined as varchar(255) but can contain Numeric, String or Date. We know the type of the current value coz we also have a type column.
But CakePHP ORM cast automatically every data to string because of the varchar definition. We must cast our datas ourself:
function ($exp) use ($data) {
return $exp->{$data['operand']}('valeur', $data['valeur'], 'integer');
};
I have 2 tables, in different databases, on the same server.
I would like to output the differences.
Database 1: dbo.employees
Table: employees
id name
--- ----
1 John
2 Ringo
3 Paul
4 George
Database 2: dbo.timecard
Table: time
timeid timename
--- ----
1 John
2 Ringo
3 Paul
Desired output:
resultid resultname
--- ----
4 George
I've set up the connection info:
<?PHP
$serverName = "server";
$UID = "dbuser";
$PWD = "dbpass";
$Database1 = "employees";
$Database2 = "timecard";
$connectionOptions1 = array("Database"=>$Database1, "UID"=>$UID, "PWD"=>$PWD);
$connectionOptions2 = array("Database"=>$Database2, "UID"=>$UID, "PWD"=>$PWD);
$conn1 = sqlsrv_connect( $serverName, $connectionOptions1);
$conn2 = sqlsrv_connect( $serverName, $connectionOptions2);
if( $conn === false )
var_dump(sqlsrv_errors());
?>
And created 2 queries:
<?PHP
$EmployeeSelect = sqlsrv_query($conn1,"SELECT * FROM dbo.employees ORDER BY name");
WHILE ($EmployeeFetch=sqlsrv_fetch_array($EmployeeSelect, SQLSRV_FETCH_ASSOC)){
ECHO $EmployeeFetch['name']." / ".$EmployeeFetch['id'];
ECHO "<BR>";
}
?>
<?PHP
$TimeSelect = sqlsrv_query($conn2,"SELECT * FROM dbo.timecard ORDER BY timename");
WHILE ($TimeFetch=sqlsrv_fetch_array($TimeSelect, SQLSRV_FETCH_ASSOC)){
ECHO $TimeFetch['timename']." / ".$TimeFetch['timeid'];
ECHO "<BR>";
}
?>
How does one deal with 2 different connection strings in a single query?
You don't need multiple connection strings since these are on the same server. Your connection will have a default database of whatever. Let's say your second query needs to pull data from another database than the default. You just need to use 3 part naming.
As a side note, you should always explicitly name your columns instead of using *.
Select *
from MySecondDatabase.dbo.timecard
I would run it as a single SQL statement instead:
SELECT E.*
FROM db1.dbo.Employee E
LEFT OUTER JOIN db2.dbo.Time T
ON E.name = T.timename
WHERE T.timename IS NULL
SELECT id,name FROM db1.dbo.Employee
EXCEPT
SELECT timeid,timename FROM db2.dbo.Time
I'm trying to compose a view that we can use to export our inventory.
I have two tables:
Inventory, which contains the columns Description, Year, Make, Model, and Serial.
Pictures, which contains the columns DocumentBody, MimeType, Serial, and Last Modified.
I'd like to make a view that has all columns from Inventory, and also adds columns for x amount of Pictures related to Serial number.
So if there were two pictures with the same serial number, the resultant table would include these fields:
Description, Year, Make, Model, Serial, DocumentBody1, MimeType1, Last Modified1, DocumentBody2, MimeType2, Last Modified2.
For those Inventory items that only have one picture, the second picture columns would all be null.
Is this something I can even do? From what I'm reading about joins, it doesn't seem possible.
As others have said, you should probably evaluate whether you actually need the view you think you need. But if you really want it, you could use PIVOT in MSSQL:
WITH BaseData AS
(
SELECT Serial
,DocumentBody
,MimeType
,LastModified
,ROWNUMBER() OVER(PARTITION BY Serial ORDER BY LastModified) AS RowNum
FROM Pictures) AS t
),
DocumentPivot AS (
SELECT
Serial
,DocumentBody
,'DocumentBody' + RowNum AS ColumnName
FROM BaseData
),
MimePivot AS (
SELECT
Serial
,MimeType
,'MimeType' + RowNum AS ColumnName
FROM BaseData
),
ModifiedPivot AS (
SELECT
Serial
,LastModified
,'LastModified' + RowNum AS ColumnName
FROM BaseData
)
SELECT Description
,Year
,Make
,Model
,Inventory.Serial
,DocumentBody1
,MimeType1
,LastModified1
,DocumentBody2
,MimeType2
,LastModified2
,...
,LastModified10
FROM Inventory
LEFT OUTER JOIN (
SELECT Serial
,DocumentBody1
,DocumentBody2
,...
,DocumentBody10
FROM DocumentPivot
PIVOT (MAX(DocumentBody) FOR ColumnName IN (DocumentBody1, DocumentBody2, ..., DocumentBody10)) AS P1
) AS Documents
ON Documents.Serial=Inventory.Serial
LEFT OUTER JOIN (
SELECT Serial
,MimeType1
,MimeType2
,...
,MimeType10
FROM MimePivot
PIVOT (MAX(MimeType) FOR ColumnName IN (MimeType1, MimeType2, ..., MimeType10)) AS P2
) AS Mimes
ON Mimes.Serial=Inventory.Serial
LEFT OUTER JOIN (
SELECT Serial
,LastModified1
,LastModified2
,...
,LastModified10
FROM ModifiedPivot
PIVOT (MAX(LastModified) FOR ColumnName IN (LastModified1, LastModified2, ..., LastModified10)) AS P3
) AS Modifieds
ON Modifieds.Serial=Inventory.Serial
Select inventory.*, count(pictures.serial) as picture_count From inventory Left Join pictures On inventory.serial = pictures.serial Where [your where statement]
Use Left Join in case there are no pictures at all. This way you still get back a result.
Update
Actually, after reading your question again, it seems you just want to extend your search results with each additional picture in the system. That's not the best way to do this. The best you can do is just get a row returned for each pic that's in the system.
Select inventory.*, pictures.DocumentBody, pictures.MimeType, pictures.Serial, pictures.Last_Modified From inventory Left Join pictures On inventory.serial = pictures.serial Where [your where statement]
Since there is no "Group By" clause, this will give you 1 row for each picture. Then you can just loop through the results.
Also
There are ways to do this by making temp tables, looping through results within a stored procedure, creating new columns (DocumentBody1, DocumentBody2, etc) for each picture result and adding the data to the new fields, then querying the temp table. But that's a lot to go through I would think.
thanks for the help everyone. In the end, I ended up using PHP to accomplish this with the following code:
<?php
date_default_timezone_set('America/Edmonton');
$serverName = "database";
$connectionInfo = array( "Database"=>"CRM_MSCRM");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn === false )
{
echo "Unable to connect.\n\n";
die( print_r( sqlsrv_errors(), true));
}
else
{
echo "Connected. Selecting trucks...\n\n";
}
$tsql = "SELECT * FROM CRM_MSCRM.dbo.Trader_Export_Simple";
$stmt = sqlsrv_query( $conn, $tsql);
if( $stmt === false )
{
echo "Error executing query.\n\n";
die( print_r( sqlsrv_errors(), true));
}
$csvData = array();
while ($row = sqlsrv_fetch_array($stmt))
{
$count = 1;
$mainpicsql = "SELECT * FROM CRM_MSCRM.dbo.TruckImages WHERE Serial = '".$row[0]."' AND MainPic = 1";
$mainpicstmt = sqlsrv_query( $conn, $mainpicsql);
while ($mainpicrow = sqlsrv_fetch_array($mainpicstmt))
{
$truck = $mainpicrow[1];
$mainfilename = $truck ."-". $count . ".png";
file_put_contents($mainfilename, base64_decode($mainpicrow[0]));
$mainpicdate = $mainpicrow[3]->format("d/m/Y h:m:s");
$mainfilename = "http://images.website/images/".$mainfilename;
echo $mainpicdate."\n";
}
$picsql = "SELECT * FROM CRM_MSCRM.dbo.TruckImages WHERE Serial = '".$row[0]."' AND MainPic = 0";
$picstmt = sqlsrv_query( $conn, $picsql);
$extrapicsdate = "";
$filenames = "";
while ($picrow = sqlsrv_fetch_array($picstmt))
{
$count++;
$filename = $picrow[1] ."-". $count . ".png";
file_put_contents($filename, base64_decode($picrow[0]));
$picdate = $picrow[3]->format("d/m/Y h:m:s");
$filenames .= "http://images.website/images/".$filename.";";
$extrapicsdate .= $picdate.";";
}
$filenames = rtrim($filenames, ";");
$extrapicsdate = rtrim($extrapicsdate, ";");
echo $filenames."\n";
echo $extrapicsdate."\n";
if ($truck != "") {
$csvData[] = array($truck, $mainfilename, $mainpicdate, $filenames, $extrapicsdate);
}
if ($filenames != "")
{
$filenames = "";
}
if ($extrapicsdate != "")
{
$extrapicsdate = "";
}
echo "Next truck...\n\n";
$truck = "";
$mainfilename = "";
$mainpicdate = "";
}
$fp = fopen('file.csv', 'w');
foreach ($csvData as $fields) {
fputcsv($fp, $fields);
}
//print_r($csvData);
sqlsrv_free_stmt( $stmt);
sqlsrv_free_stmt( $picstmt);
sqlsrv_close( $conn);
?>
this gets the files out but I still have to merge the resultant CSV with the main "information" CSV.
i am using cakephp and creating this condition:
$conditions = array("Userword.levelid"=>0, "Userword.userid"=>$this->Auth->user('UserId'),"date(Userword.date)"=>"DATE_SUB(CURDATE(),INTERVAL 0 DAY)");
$Userword = $this->paginate(null, $conditions);
cake using this select :
`Userword`.`userwordid`, `Userword`.`userid`, `Userword`.`wordid`, `Userword`.`date`, `Userword`.`levelid`, `Word`.`wordid`, `Word`.`word`, `Word`.`meaning`, `User`.`UserId`, `User`.`Email`, `User`.`password`, `User`.`username`, `User`.`cell`, `User`.`web` FROM `userwords` AS `Userword` LEFT JOIN `words` AS `Word` ON (`Userword`.`wordid` = `Word`.`wordid`) LEFT JOIN `users` AS `User` ON (`Userword`.`userid` = `User`.`UserId`) WHERE date(`Userword`.`date`) = 'DATE_SUB(CURDATE(),INTERVAL 2 DAY)'
but by this select mysql can't return record because cakephp in this select use this character (') in last passage.
when i remove this character and test this code in phpmyadmin this code return rows. two images in below show this :
Just don't separate it out as key => value pair:
$conditions = array(
...
'DATE(Userword.date) = DATE_SUB(CURDATE(), INTERVAL 0 DAY)'
);