Symfony QueryBuilder - filter collection in query - database

I have a query like this:
return $this->createQueryBuilder('supervision')
->join('supervision.supervisionEvents', 'supervisionEvents')
->andWhere('supervisionEvents.episode = :episode')
->setParameter('episode', $episode)
->getQuery()
->getResult()
;
I want to get all supervisions but the supervisionEvents I want to filter.
In result I only want to have SupervisionEvents with episode = :episode.
I used join, leftJoin and innerJoin. Nothing works like desired.
I tried to have a condition on the join:
->innerJoin('s.supervisionEvents', 'supervisionEvent', 'WITH', 'supervisionEvent.episode = :episode')
But thats also not working!

You are actually pretty close. You want to filter only on the join, so use a left join with condition to the join clause:
return $this->createQueryBuilder('supervision')
->addSelect('supervisionEvents')
->leftJoin('supervision.supervisionEvents', 'supervisionEvents', Join::WITH, 'supervisionEvents.episode = :episode')
->setParameter('episode', $episode)
->getQuery()
->getResult()
;
It is needed also to select the joined relation, so that it is hydrated on the result.
References
doctrine left join with condition
Why and when a LEFT JOIN with condition in WHERE clause is not equivalent to the same LEFT JOIN in ON

Related

Difference between Filter in join verses filter in where clause (T-sql)

Using Microsoft T-SQL, I know there is a difference in the result set between putting a filter in the join verses putting the filter in the where clause, because I get a different row count, and its hard to pin point, because it is a complex query with thousands of rows.
So does anybody know how this might lead to different results?
I feel safer with the where clause, but I am curious why the other one didn't get the same results.
Select
.....
left outer join
datamart_agent ag on a.CUSTOMER_TKN = ag.customer_tkn
and a.CUSTOMER_ACCT_TKN = ag.customer_acct_tkn
and a.ACCOUNT_PKG_TKN = ag.account_pkg_tkn
--where (commented out)
and ag.TYPE_DESC = 'Agent'
versus
Select
.....
left outer join
datamart_agent ag on a.CUSTOMER_TKN = ag.customer_tkn
and a.CUSTOMER_ACCT_TKN = ag.customer_acct_tkn
and a.ACCOUNT_PKG_TKN = ag.account_pkg_tkn
where
--and (commented out)
ag.TYPE_DESC = 'Agent'
If condition is in your where clause then it will drop all records for which no match was found. It is a like an eraser. I deletes all records for which no match was found (Type_Desc is null).
The safer thing, if you are actually seeking left join, is to put the condition in the on clause. If there was no match, it will still come in the result. When Type_Desc is null, it means you don't know who the agent is, but if you don't know, you don't want to delete the record....

SQL Server SSRS query Issue

I have the following query:
SELECT
pupils.txtSchoolID, pupils.txtPreName, pupils.txtSurname,
pupils.txtForm, pupils.txtAdditionalHealth, pupils.txtAllergyNotes,
notes.txtNote
FROM
TblPupilManagementPupils AS pupils
LEFT OUTER JOIN
TblPupilManagementHealthNotes AS notes ON pupils.txtSchoolID = notes.txtSchoolID
I need to only pull the notes.txtNote when notes.txtType = 'Dietary', however, when I set this in a WHERE clause, I only get entries with Type Dietary, I still need all of the pupil's table data also. I thought the left outer join would do this.
When setting the WHERE clause, I try
WHERE notes.txtType = 'Dietary'
but this also does not work, I have been setting as a parameter temporarily.
you have to remove where clause and put that condition on clause because
Logically, all JOINs are performed as INNER JOINs using the ON filters, and then, as a subsequent step, any OUTER JOIN rows are added back to the necessary side. After all JOINs are complete is the WHERE filter processed. as a result when you applied it on where it removed all expect Dietary values records
SELECT pupils.txtSchoolID, pupils.txtPreName, pupils.txtSurname,
pupils.txtForm, pupils.txtAdditionalHealth, pupils.txtAllergyNotes,
notes.txtNote
FROM TblPupilManagementPupils AS pupils LEFT OUTER JOIN
TblPupilManagementHealthNotes AS notes
ON pupils.txtSchoolID = notes.txtSchoolID and notes.txtType = 'Dietary'
Put the condition (notes.txtType = 'Dietary') with ON clause :
. . .
FROM TblPupilManagementPupils AS pupils LEFT OUTER JOIN
TblPupilManagementHealthNotes AS notes
ON pupils.txtSchoolID = notes.txtSchoolID AND notes.txtType = 'Dietary';
If you filter the LEFT OUTER JOINED table data with WHERE clause, then you are making a join as INNER JOIN instead of LEFT JOIN.
Alternatively less optimized route is; run your query as is with no where clause and no additional on clause. Insert data into temp table and then filter that data as so; where notes.txtType = #Param . and this #Param you declare topside for stored procedure or query as #Param varchar(200) to capture whatever expected front end value your expecting.

Update with Inner join or subquery - multiple relations

I need and update on Table exp_pedcom on cases where a field of another table are null ( EXP_Procimp), but these two table do not have a direct relation to each other, so I actully need to "route" it though two other tables in order to relate them. The "routed! relation works, it returns as expected, but the update doesn't. I've tryed both as a direct inner join using from and as a subquery ( which is actually easier to demonstrate, so That's what goes here.
UPDATE EXP_PEDCOM
SET STATUS_ATENDIMENTO=0
WHERE EXP_PROCIMP.DAT_RECEBIMENTO IS NOT NULL IN (SELECT EXP_PROCIMP.DAT_RECEBIMENTO
FROM
EXP_PEDCOM INNER JOIN
EXP_INVOICE_IT ON EXP_PEDCOM.NUM_PEDCOM = EXP_INVOICE_IT.NUM_PEDCOM INNER JOIN
EXP_INVOICE ON EXP_INVOICE_IT.COD_DOCUMENTO = EXP_INVOICE.COD_DOCUMENTO INNER JOIN
EXP_PROCIMP ON EXP_INVOICE.NUM_PROCIMP = EXP_PROCIMP.NUM_PROCIMP)
Any tips?
The following shows how to use it using the UPDATE... FROM... syntax. (I messed with formatting and aliases while working out what the query actually did.)
UPDATE EXP_PEDCOM
set STATUS_ATENDIMENTO = 0
from EXP_PEDCOM
inner join EXP_INVOICE_IT it
on EXP_PEDCOM.NUM_PEDCOM = it.NUM_PEDCOM
inner join EXP_INVOICE iv
on it.COD_DOCUMENTO = iv.COD_DOCUMENTO
inner join EXP_PROCIMP pr
on iv.NUM_PROCIMP = pr.NUM_PROCIMP
where pr.DAT_RECEBIMENTO is not null
This will work [caveat: I could not run and so debug possible syntax glitches], but it's hard to explain why/how this works. It's also a tad unconventional; hopefully you'll get other posts that show the "proper" way to run such queries.

PDO Join, avoid overwriting keys with the same name in the resulted array

I am doing a join with PDO like this:
SELECT users.*,images.*, sessions.*,social.*,videos.*,teams.*,achievements.*,_achievements_list.* FROM users LEFT JOIN images ON users.user_id=images.user_id LEFT JOIN sessions ON users.user_id=sessions.user_id LEFT JOIN social ON users.user_id=social.user_id LEFT JOIN videos ON users.user_id=videos.user_id LEFT JOIN teams ON users.user_id=teams.user_id LEFT JOIN achievements ON users.user_id=achievements.user_id LEFT JOIN _achievements_list ON achievements.achievement_id=_achievements_list.parent_id WHERE users.nickname = 'something'
The problem is that some tables have the same names for some columns, so in the array that PDO gives me back, many things are overwritten.
I am using this:
$statement = $this->pdo->prepare($query);
if ($statement->execute($param))
return $statement->fetchAll(PDO::FETCH_ASSOC);
return false;
PDO returns an associative array, but how do I do in order to avoid overwriting columns with the same names but from different tables?
you can use PDO::FETCH_NAMED, see https://phpdelusions.net/pdo/fetch_modes#FETCH_NAMED
it is very not recommended to use .* because :
if the table structure changes, then your column indexes change, and if you used to read by index, then Too bad.
mostly, you really dont need all the columns and therefore you will reduce the amount of data you retrieve from the server (if it is remote then it might even be meanningful)
Anyway, if you dont use .* you can use Aliases in your SQL Query
like
SELECT products.id prodId, orders.id orderId FROM Orders LEFT JOIN Products ON (prodId = orders.product_id) WHERE orderId = #oid

left join not showing null values

I need to find the items that exist in table A but not in table B. Now that would be really simple in MySQL doing a join like this
select * from A
left join B on A.key=B.key
where B.key is null
However for some reason this is not working in MSSQL. I have created the query without the where clause to see all the results and I only see matches, not null values. Do you have any idea why this is not working?
I know I can alternatively use "when not exists" but I want to know the reason as to why with a join is not working.
I am adding the code for your review
select Absences.CustomerID, b.*
from (
select * from openquery(JUAN_INTERFACE,'select cmp_wwn from Planet_Customers where i_outcome =4')) b
left join Absences on Absences.CustomerID = b.cmp_wwn
where Absences.Type = 3223
Your where clause is filtering out null values:
where Absences.Type = 3223
You are left-joining from the openquery subquery to Absences; and then filtering only rows that have a specific (non-null) value in an Absences column.
Did you mean to join the other way around, from Absenses to openquery?

Resources