Phalcon ExecuteQuery inner Join issues - phalcon

This is Native SQL Query, thats work in MySql:
SELECT a.pshdQty
FROM production_stock_header a
INNER JOIN (SELECT MAX(pshdId) AS pshdId
FROM production_stock_header
WHERE pshdAuditDelete = 'N'
) b
ON a.pshdId = b.pshdId
But, why in Phalcon this always errors?
$triggerSet = $this->modelsManager->executeQuery("
SELECT pshdQty
FROM ProductionStockHeader
INNER JOIN (SELECT MAX(pshdId) AS pshdId
FROM ProductionStockHeader
WHERE ProductionStockHeader.AuditDelete = 'N'
) AS b
ON ProductionStockHeader.pshdId = b.pshdId
");

Phalcon ORM doesn't provide a way to write such join statements.
I'd suggest to just run a raw native SQL query on your db connection:
$triggerSet = $this->db->query("SELECT a.pshdQty
FROM production_stock_header a
INNER JOIN (SELECT MAX(pshdId) AS pshdId
FROM production_stock_header
WHERE pshdAuditDelete = 'N'
) b
ON a.pshdId = b.pshdId")->fetch();
$this->db points to your database connection you registered in your services.
You can also drop the inner join all together:
$triggerSet = $this->modelsManager->executeQuery("
SELECT pshdQty
FROM ProductionStockHeader
WHERE AuditDelete = 'N'
ORDER BY pshdId DESC
LIMIT 1
");

Related

How do I fix the syntax of a sub query with joins?

I have the following query:
SELECT tours_atp.NAME_T, today_atp.TOUR, today_atp.ID1, odds_atp.K1, today_atp.ID2, odds_atp.K2
FROM (players_atp INNER JOIN (players_atp AS players_atp_1 INNER JOIN (today_atp INNER JOIN odds_atp ON (today_atp.TOUR = odds_atp.ID_T_O) AND (today_atp.ID1 = odds_atp.ID1_O) AND (today_atp.ID2 = odds_atp.ID2_O) AND (today_atp.ROUND = odds_atp.ID_R_O)) ON players_atp_1.ID_P = today_atp.ID2) ON players_atp.ID_P = today_atp.ID1) INNER JOIN tours_atp ON today_atp.TOUR = tours_atp.ID_T
WHERE (((tours_atp.RANK_T) Between 1 And 4) AND ((today_atp.RESULT)="") AND ((players_atp.NAME_P) Not Like "*/*") AND ((players_atp_1.NAME_P) Not Like "*/*") AND ((odds_atp.ID_B_O)=2))
ORDER BY tours_atp.NAME_T;
I'd like to add a field to this query that provides me with the sum of a field in another table (FS) with a few criteria applied.
I've been able to build a stand alone query to get the sum of FS by ID_T as follows:
SELECT tbl_Ts_base_atp.ID_T, Sum(tbl_Ts_mkv_atp.FS) AS SumOfFS
FROM tbl_Ts_base_atp INNER JOIN tbl_Ts_mkv_atp ON tbl_Ts_base_atp.ID_Ts = tbl_Ts_mkv_atp.ID_Ts
WHERE (((tbl_Ts_base_atp.DATE_T)>Date()-2000 And (tbl_Ts_base_atp.DATE_T)<Date()))
GROUP BY tbl_Ts_base_atp.ID_T, tbl_Ts_mkv_atp.ID_Ts;
I now want to match up the sum of FS from the second query to the records of the first query by ID_T. I realise I need to do this using a sub query. I'm confident using these when there's only one table but I consistently get 'syntax errors' when there are joins.
I simplified the first query down to remove all the WHERE conditions so it was easier for me to try and error check but no luck. I guess the resulting SQL will also be easier for you guys to follow:
SELECT today_atp.TOUR, (SELECT Sum(tbl_Ts_mkv_atp.FS)
FROM tbl_Ts_mkv_atp INNER JOIN (tbl_Ts_base_atp INNER JOIN today_atp ON tbl_Ts_base_atp.ID_T = today_atp.TOUR) ON tbl_Ts_mkv_atp.ID_Ts = tbl_Ts_base_atp.ID_Ts AS tt
WHERE tt.DATE_T>Date()-2000 And tt.DATE_T<Date() AND tt.TOUR=today_atp.TOUR
ORDER BY tt.DATE_T) AS SumOfFS
FROM today_atp
Can you spot where I'm going wrong? My hunch is that the issue is in the FROM line of the sub query but I'm not sure. Thanks in advance.
It's difficult to advise an appropriate solution without knowledge of how the database tables relate to one another, but assuming that I've correctly understood what you are looking to achieve, you might wish to try the following solution:
select
tours_atp.name_t,
today_atp.tour,
today_atp.id1,
odds_atp.k1,
today_atp.id2,
odds_atp.k2,
subq.sumoffs
from
(
(
(
(
today_atp inner join odds_atp on
today_atp.tour = odds_atp.id_t_o and
today_atp.id1 = odds_atp.id1_o and
today_atp.id2 = odds_atp.id2_o and
today_atp.round = odds_atp.id_r_o
)
inner join players_atp as players_atp_1 on
players_atp_1.id_p = today_atp.id2
)
inner join players_atp on
players_atp.id_p = today_atp.id1
)
inner join tours_atp on
today_atp.tour = tours_atp.id_t
)
inner join
(
select
tbl_ts_base_atp.id_t,
sum(tbl_ts_mkv_atp.fs) as sumoffs
from
tbl_ts_base_atp inner join tbl_ts_mkv_atp on
tbl_ts_base_atp.id_ts = tbl_ts_mkv_atp.id_ts
where
tbl_ts_base_atp.date_t > date()-2000 and tbl_ts_base_atp.date_t < date()
group by
tbl_ts_base_atp.id_t
) subq on
tours_atp.tour = subq.id_t
where
(tours_atp.rank_t between 1 and 4) and
today_atp.result = "" and
players_atp.name_p not like "*/*" and
players_atp_1.name_p not like "*/*" and
odds_atp.id_b_o = 2
order by
tours_atp.name_t;

JOIN syntax and order for multiple tables

SQL Gurus,
I have a query that uses the "old" style of join syntax as follows using 7 tables (table and column names changed to protect the innocent), as shown below:
SELECT v1_col, p1_col
FROM p1_tbl, p_tbl, p2_tbl, p3_tbl, v1_tbl, v2_tbl, v3_tbl
WHERE p1_code = 1
AND v1_code = 1
AND p1_date >= v1_date
AND p_uid = p1_uid
AND p2_uid = p1_uid AND p2_id = v2_id
AND p3_uid = p1_uid AND p3_id = v3_id
AND v2_uid = v1_uid
AND v3_uid = v1_uid
The query works just fine and produces the results it is supposed to, but as an academic exercise, I tried to rewrite the query using the more standard JOIN syntax, for example, below is one version I tried:
SELECT V1.v1_col, P1.p1_col
FROM p1_tbl P1, v1_tbl V1
JOIN p_tbl P ON ( P.p_uid = P1.p1_uid )
JOIN p2_tbl P2 ON ( P2.p2_uid = P1.p1_uid AND P2.p2_id = V2.v2_id )
JOIN p3_tbl P3 ON ( P3.p3_uid = P1.p1_uid AND P3.p3_id = V3.v3_id )
JOIN v2_tbl V2 ON ( V2.v2_uid = V1.v1_uid )
JOIN v3_tbl V3 ON ( V3.v3_uid = V1.v1_uid )
WHERE P1.p1_code = 1
AND V1.v1_code = 1
AND P1.p1_date >= V1.v1_date
But, no matter how I arrange the JOINs (using MS SQL 2008 R2), I keep running into the error:
The Multi-part identifier "col-name" could not be bound,
where "col-name" varies depending on the order of the JOINs I am attempting...
Does anyone have any good examples on how use the JOIN syntax with this number of tables??
Thanks in advance!
When you use JOIN-syntax you can only access columns from tables in your current join or previous joins. In fact it's easier to write the old syntax, but it's more error-prone, e.g. you can easily forget a join-condition.
This should be what you want.
SELECT v1_col, p1_col
FROM p1_tbl
JOIN v1_tbl ON p1_date >= v1_date
JOIN v2_tbl ON v2_uid = v1_uid
JOIN v3_tbl ON v3_uid = v1_uid
JOIN p_tbl ON p_uid = p1_uid
JOIN p2_tbl ON p2_uid = p1_uid AND p2_id = v2_id
JOIN p3_tbl ON p3_uid = p1_uid AND p3_id = v3_id
WHERE p1_code = 1
AND v1_code = 1
You are not naming the tables in your join such that it doesn't know which column is from which table. Try something like:
SELECT a.v1_col, b.p1_col
FROM p1_tbl b
JOIN p_tbl a ON b.p_uid = a.p1_uid
WHERE b.p1_code = 1
From your query above, I am assuming a naming convention of p2_uid comes from p2_tbl. Below id my best interpretation of WHERE joins to using INNER joins.
SELECT
v1_col, p1_col
FROM
p1_tbl
INNER JOIN p1_tbl
ON p1_tbl.p1_date >= v1_tbl.v1_date
INNER JOIN p_tbl
ON p_tbl.p_uid = p1_tbl.p1_uid
INNER JOIN p2_tbl
ON p2_tbl.p2_uid = p1_tbl.p1_uid
INNER JOIN v2_tbl
ON p2_tbl.p2_id = v2_tbl.v2_id
INNER JOIN p3_tbl
ON p3_tbl.p3_uid = p1_tbl.p1_uid
INNER JOIN v3_tbl
ON p3_tbl.p3_id = v3_tbl.v3_id
INNER JOIN v1_tbl
ON v1_tbl.v1_uid = v2_tbl.v2_uid
AND v1_tbl.v1_uid = v3_tbl.v2_uid
WHERE
p1_code = 1
AND
v1_code = 1
Some general points I have found useful in SQL statements with many joins.
Always fully qualify the names. I.e dont use ID , rahter use
TableName.ID
Dont use aliases unless there is meaning. (I.e. joining a table to
its self where aliasing is needed.)

I'm trying to update the data in table column "Supplier_Base.CreditBalance" with the sum of the colum "Purch" in table "Suppliers_Account"

This was what i'm trying but it does not work.
UPDATE
dbo.Supplier_Base SET dbo.Supplier_Base.CreditBalance (
SELECT
SUM(dbo.Suppliers_Account.Purch ) AS BAL,
FROM
dbo.Suppliers_Account
INNER JOIN
dbo.Supplier_Base ON dbo.Suppliers_Account.Code = dbo.Supplier_Base.Code
GROUP BY dbo.Suppliers_Account.Code, dbo.Supplier_Base.CreditBalance
HAVING (dbo.Suppliers_Account.Code = N'C003'))
Sub-queries aren't allowed in a SET statement. You can work around this by aliasing the tables and doing a JOIN instead.
Do you have a test environment where you can run queries with damaging production data? I think this is what you're looking for, but DO test it first:
UPDATE
b
SET
b.CreditBalance = SUM(a.Purch)
FROM
dbo.Suppliers_Account a
INNER JOIN
dbo.Supplier_Base b
ON
a.Code = b.Code
WHERE
a.Code = N'C003'
GROUP BY
a.Code
This is the correct syntax:
UPDATE SB
SET CreditBalance = SA.Purch
FROM dbo.Supplier_Base SB
INNER JOIN (SELECT Code, SUM(Purch) Purch
FROM dbo.Suppliers_Account)
GROUP BY Code) SA
ON SB.Code = SA.Code
WHERE SB.Code = N'C003'

Select from named query

I have issue with following query in MS Access 2013:
SELECT *
FROM (((
(SELECT Stop.TAGeoID AS TAGeoID,
Trip.TripNo AS TripNo
FROM ((((Trip
INNER JOIN BTStopTimes ON Trip.TripNo = BTStopTimes.TripNumber)
INNER JOIN TripsTxt ON (Trip.TripNo = TripsTxt.trip_id
AND Left(TripsTxt.shape_id, 3) <> 'ELD'))
INNER JOIN PatternDetail ON Trip.PatternID = PatternDetail.PatternID
AND BTStopTimes.Sequence = PatternDetail.StopSortOrder)
INNER JOIN Stop ON Stop.GeoID = PatternDetail.GeoID)) AS t3
LEFT JOIN
(SELECT F10,
F16
FROM PatternStopsRaw
WHERE F16 <> ''
GROUP BY F10,
F16)R ON R.F10 = t3.TAGeoID)
LEFT JOIN Timepoint ON Timepoint.PlaceID = R.F16)
LEFT JOIN
(SELECT *
FROM t3
INNER JOIN TripDetail ON t3.TripNo = TripDetail.TripNo)TripTripDetail ON (Timepoint.TimePointID = TripTripDetail.TimepointID))
It says that there is syntax error
The Microsoft Access database engine cannot find the input table or query t3. Make sure it exists and that its name is spelled correctly
It seems that Access does not allow selecting from the named query in the same query.
Any suggestions?
PS: * are used only for testing purposes, I'll remove them once I have working query.
Yes, it appears that Access does not recognize the [t3] alias at that level. Perhaps you could try creating the query...
SELECT Stop.TAGeoID AS TAGeoID,
Trip.TripNo AS TripNo
FROM ((((Trip
INNER JOIN BTStopTimes ON Trip.TripNo = BTStopTimes.TripNumber)
INNER JOIN TripsTxt ON (Trip.TripNo = TripsTxt.trip_id
AND Left(TripsTxt.shape_id, 3) <> 'ELD'))
INNER JOIN PatternDetail ON Trip.PatternID = PatternDetail.PatternID
AND BTStopTimes.Sequence = PatternDetail.StopSortOrder)
INNER JOIN Stop ON Stop.GeoID = PatternDetail.GeoID)
...as a saved query in Access, name it [t3], and then just reference that in your main query.

SQL Server 'FOR XML PATH' in PHP/MySQL

I have a SQL Server query that I need to convert to MySQL. I've never used SQL Server/T-SQL before, so I have no experience with FOR XML PATH. There's surprisingly little documentation on this sort of thing. If I remove the FOR XML PATH statement, MySQL returns the error "Operand should contain at least 1 column(s)."
It seems like the nested SELECT statements return strings containing raw XML data, but I don't have the original SQL Server database available to test that theory. I could emulate this effect easily if I knew the return schema.
The original query is below:
SELECT
har_autos.*, har_automodels.Model, har_automodels.MakeID, har_automakes.Make, har_autotypes.AutoType,
(SELECT har_notes.*, har_notelinks.Value
FROM har_notes
JOIN har_notelinks on (har_notes.ID = har_notelinks.NoteID)
WHERE har_autos.ID = har_notelinks.AutoID AND har_notes.NoteTypeID = 1)
AS 'UserNotes',
(SELECT har_notes.*, har_notelinks.Value
FROM har_notes
JOIN har_notelinks on (har_notes.ID = har_notelinks.NoteID)
WHERE har_autos.ID = har_notelinks.AutoID AND har_notes.NoteTypeID = 2)
AS 'EngineeringNotes'
FROM har_autos
LEFT JOIN har_automodels ON (har_autos.ModelID = har_automodels.ID)
LEFT JOIN har_automakes ON (har_automodels.MakeID = har_automakes.ID)
LEFT JOIN har_autotypes ON (har_autos.AutoTypeID = har_autotypes.ID)
UPDATE:
I rebuilt the query in its entirety and it now returns "Not unique table/alias: 'har_automakes'."
SELECT
har_autos.*,
har_automodels.Model,
har_automodels.MakeID,
har_automakes.Make,
har_autotypes.AutoType,
(SELECT
har_notes.ID,
har_notes.NoteTypeID,
har_notes.Text001,
har_notelinks.Value,
har_notelinks.AutoID,
har_autos.ID
FROM
har_notes
INNER JOIN har_notelinks ON (har_notes.ID = har_notelinks.NoteID),
har_autos
WHERE har_autos.ID = har_notelinks.AutoID AND har_notes.NoteTypeID = 1)
AS UserNotes,
(SELECT
har_notes.ID,
har_notes.NoteTypeID,
har_notes.Text001,
har_notelinks.Value,
har_notelinks.AutoID,
har_autos.ID
FROM
har_notes
INNER JOIN har_notelinks ON (har_notes.ID = har_notelinks.NoteID), har_autos
WHERE har_autos.ID = har_notelinks.AutoID AND har_notes.NoteTypeID = 2)
AS EngineeringNotes
FROM
har_autos
LEFT OUTER JOIN har_automodels ON (har_autos.ModelID = har_automodels.ID)
LEFT OUTER JOIN har_autotypes ON (har_autos.AutoTypeID = har_autotypes.ID),
har_automakes
LEFT OUTER JOIN har_automakes ON (har_automakes.MakeID = har_automakes.ID)
WHERE
ID = 1
This is the original T-SQL query (really sorry about all of these):
SELECT a.*, mo.Model, mo.MakeID, ma.Make, at.AutoType,
(SELECT n.*, nl.Value
FROM dbo.Notes n
JOIN dbo.NoteLinks nl on (n.ID = nl.NoteID)
WHERE a.ID = nl.AutoID AND n.NoteTypeID = 1
FOR XML PATH('Note'), TYPE
) AS 'UserNotes',
(SELECT n.*, nl.Value
FROM dbo.Notes n
JOIN dbo.NoteLinks nl on (n.ID = nl.NoteID)
WHERE a.ID = nl.AutoID AND n.NoteTypeID = 2
FOR XML PATH('Note'), TYPE
) AS 'EngineeringNotes'
FROM dbo.Autos a
LEFT JOIN dbo.AutoModels mo ON (a.ModelID = mo.ID)
LEFT JOIN dbo.AutoMakes ma ON (mo.MakeID = ma.ID)
LEFT JOIN dbo.AutoTypes at ON (a.AutoTypeID = at.ID)
Little Documentation:
Using PATH Mode
Basic Syntax of the FOR XML Clause
Examples: Using PATH Mode
Constructing XML Using FOR XML
All of the above are from the following search: http://social.technet.microsoft.com/Search/en-US/?Refinement=129&Query=for+xml+path.