Join with Zend_Db, without having the columns of the joined tables - sql

I use Zend_Db_Select to perform a query with a Join. I end up with the following SQL query :
SELECT `Utilisateur`.*, `Ressource`.*, `Acl_Cache`.*, `Role`.*, `UtilisateurRole`.* FROM `Utilisateur`
INNER JOIN `Ressource` ON Ressource.idJointure = Utilisateur.id
INNER JOIN `Acl_Cache` ON Acl_Cache.idRessource = Ressource.id
INNER JOIN `Role` ON Role.id = Acl_Cache.idRole
INNER JOIN `UtilisateurRole` ON UtilisateurRole.idRole = Role.id
WHERE (Ressource.tableJointure = 'Utilisateur') AND (UtilisateurRole.idUtilisateur = '2')
Why is Zend_Db adding this part is the SELECT clause :
, `Ressource`.*, `Acl_Cache`.*, `Role`.*, `UtilisateurRole`.*
I never asked this, and I don't want that. How to prevent this behavior ?

$db->select()
->from(array('alias1'=>'table_i_want_all_cols_on'))
->joinLeft(array('alias2'=>'table_i_want_no_cols_on'),
'alias1.id = alias2.id',
array()
)
->joinLeft(array('alias3'=>'table_i_want_some_cols_on'),
'alias3.id = alias1.id',
array('col1', 'col2')
);

Related

How can I transform this Code with Joins instead of using +(=) or =

I was trying Hours to transform this code(I think It is Oracle) with joins in SQL Server instead of
using +(=)/= but somehow i dont get the same result as using += or =. Can please someone help me out ?
SELECT KNVV.MANDT, KNVV.KUNNR,
KNVV.VTWEG, KNVV.BZIRK, KNVP.KUNN2
FROM KNA1, KNVV, KNVP, CDHDR
WHERE
AND `(KNVV.MANDT = KNA1.MANDT`
AND `KNVV.KUNNR = KNA1.KUNNR)`
AND `(KNVP.MANDT (+) = KNVV.MANDT`
AND `KNVP.KUNNR (+) = KNVV.KUNNR`
AND `KNVP.VTWEG (+) = KNVV.VTWEG)`
AND `(CDHDR.MANDANT (+) = KNVV.MANDT`
AND `CDHDR.OBJECTID (+) = KNVV.KUNNR)`
AND `(KNVV.VTWEG = KNVP.VTWEG)`
AND `KNVP.PARVW (+) = 'RG'`
AND CDHDR.OBJECTCLAS (+) = 'DEBI'
Without sample data its hard to test but it appears you want:
SELECT KNVV.MANDT, KNVV.KUNNR,
KNVV.VTWEG, KNVV.BZIRK, KNVP.KUNN2
FROM KNA1
INNER JOIN KNVV
ON ( KNVV.MANDT = KNA1.MANDT
AND KNVV.KUNNR = KNA1.KUNNR
)
INNER JOIN KNVP
ON ( KNVP.MANDT = KNVV.MANDT
AND KNVP.KUNNR = KNVV.KUNNR
AND KNVP.VTWEG = KNVV.VTWEG
AND KNVV.VTWEG = KNVP.VTWEG -- This duplicated condition makes it an
-- INNER JOIN and not a LEFT OUTER JOIN as
-- you are not using (+) in Oracle's legacy
-- syntax.
AND KNVP.PARVW = 'RG'
)
LEFT OUTER JOIN CDHDR
ON ( CDHDR.MANDANT = KNVV.MANDT
AND CDHDR.OBJECTID = KNVV.KUNNR
AND CDHDR.OBJECTCLAS = 'DEBI'
)
What you probably want is to make the second join a LEFT OUTER JOIN instead of an INNER JOIN but that is not what your current query is doing as you are using (KNVV.VTWEG = KNVP.VTWEG) rather than (KNVV.VTWEG = (+) KNVP.VTWEG) in your Oracle query.
You query can be converted to:
select
KNVV.MANDT,
KNVV.KUNNR,
KNVV.VTWEG,
KNVV.BZIRK,
KNVP.KUNN2
from KNA1
join KNVV on KNVV.MANDT = KNA1.MANDT
and KNVV.KUNNR = KNA1.KUNNR
left join KNVP on KNVP.MANDT = KNVV.MANDT -- left join defeated!
and KNVP.KUNNR = KNVV.KUNNR
and KNVP.VTWEG = KNVV.VTWEG
and KNVP.PARVW = 'RG'
left join CDHDR on CDHDR.MANDANT = KNVV.MANDT
and CDHDR.OBJECTID = KNVV.KUNNR
and CDHDR.OBJECTCLAS = 'DEBI'
where KNVV.VTWEG = KNVP.VTWEG -- silently converts left join into inner join
NOTE: the original query is malformed
Even though the original query tried to perform a left join against the table KNVP this join is silently converted into an inner join by the engine. Are you sure this query is working as expected?
Did you try inner JOIN?
SELECT KNVV.MANDT, KNVV.KUNNR,
KNVV.VTWEG, KNVV.BZIRK, KNVP.KUNN2
FROM KNA1, KNVV, KNVP, CDHDR
INNER JOIN KNVV ON KNA1.MANDT=KNVV.MANDT;
Something in this sense its more convenient.
documentation bellow
https://www.w3schools.com/sql/sql_join.asp

Passing different column values to where clause

SELECT pims.icicimedicalexaminerreport.id,
pims.icicimerfemaleapplicant.adversemenstrualid,
pims.icicimerfemaleapplicant.pregnantid,
pims.icicimerfemaleapplicant.miscarriageabortionid,
pims.icicimerfemaleapplicant.breastdiseaseid,
pims.pimscase.tiannumber
FROM pims.pimscase
INNER JOIN pims.digitization
ON pims.pimscase.digitizationid = pims.digitization.id
INNER JOIN pims.medicalexaminerreport
ON pims.digitization.medicalexaminerreportid =
pims.medicalexaminerreport.id
INNER JOIN pims.icicimedicalexaminerreport
ON pims.medicalexaminerreport.id =
pims.icicimedicalexaminerreport.id
INNER JOIN pims.icicimerfemaleapplicant
ON pims.icicimedicalexaminerreport.id =
pims.icicimerfemaleapplicant.id
WHERE pims.pimscase.tiannumber = 'ICICI1234567890'
which gives me the following output
Now I want to use the above output values to select the rows from the table "YesNoAnswerWithObservation"
I imagine it should look something like this Select * from YesNoAnswerWithObservation Where Id in (22,27,26,...23)
Only instead of typing the values inside IN clause I want to use the values in each column resulting from above-mentioned query.
I tried the below code but it returns all the rows in the table rather than rows mentioned inside the In
SELECT pims.yesnoanswerwithobservation.observation,
graphitegtccore.yesnoquestion.description,
pims.yesnoanswerwithobservation.id ObservationId
FROM pims.yesnoanswerwithobservation
INNER JOIN graphitegtccore.yesnoquestion
ON pims.yesnoanswerwithobservation.yesnoanswerid =
graphitegtccore.yesnoquestion.id
WHERE EXISTS (SELECT pims.icicimedicalexaminerreport.id,
pims.icicimerfemaleapplicant.adversemenstrualid,
pims.icicimerfemaleapplicant.pregnantid,
pims.icicimerfemaleapplicant.pelvicorgandiseaseid,
pims.icicimerfemaleapplicant.miscarriageabortionid,
pims.icicimerfemaleapplicant.gynocologicalscanid,
pims.icicimerfemaleapplicant.breastdiseaseid,
pims.pimscase.tiannumber
FROM pims.pimscase
INNER JOIN pims.digitization
ON pims.pimscase.digitizationid =
pims.digitization.id
INNER JOIN pims.medicalexaminerreport
ON pims.digitization.medicalexaminerreportid =
pims.medicalexaminerreport.id
INNER JOIN pims.icicimedicalexaminerreport
ON pims.medicalexaminerreport.id =
pims.icicimedicalexaminerreport.id
INNER JOIN pims.icicimerfemaleapplicant
ON pims.icicimedicalexaminerreport.id =
pims.icicimerfemaleapplicant.id
WHERE pims.pimscase.tiannumber = 'ICICI1234567890')
Any help or a nudge in the right direction would be greatly appreciated
Presumably you want the ids from the first query:
SELECT awo.observation, ynq.description, ynq.id as ObservationId
FROM pims.yesnoanswerwithobservation awo JOIN
graphitegtccore.yesnoquestion ynq
ON awo.yesnoanswerid = ynq.id
WHERE ynq.id = (SELECT mer.id
FROM pims.pimscase c JOIN
pims.digitization d
ON c.digitizationid = d.id JOIN
pims.medicalexaminerreport mer
ON d.medicalexaminerreportid = mer.id JOIN
pims.icicimedicalexaminerreport imer
ON mer.id = imer.id JOIN
pims.icicimerfemaleapplicant ifa
ON imer.id = ifa.id
WHERE c.tiannumber = 'ICICI1234567890'
) ;
Notice that table aliases make the query much easier to write and to read.

DB2 SQL multiple JOIN issue

I have a query with two JOIN and it does not work. I get no errors. It just does not return any records. If I separate my query then it works. What Am I doing wrong here?
When I split up the query I get one record each which is what I should get.
Full query:
SELECT HPOL07.*, #RFC.*, #AAM.*
FROM BPCSPROF.HPOL07
JOIN BPCSPROF.#RFC ON PRFC = #RFC.RFCNUM AND PPRF = #RFC.RFCPRC
AND PGLNO = #RFC.RFCGLN
JOIN BPCSPROF.#AAM ON PPRF = #AAM.AAMPRC AND PGLNO = #AAM.AAMGLN
WHERE PORD = '605400' AND PID <> 'PZ'
Separate queries:
SELECT HPOL07.*, #RFC.*
FROM BPCSPROF.HPOL07
JOIN BPCSPROF.#RFC ON PRFC = #RFC.RFCNUM AND PPRF = #RFC.RFCPRC
AND PGLNO = #RFC.RFCGLN
WHERE PORD = '605400' AND PID <> 'PZ'
SELECT HPOL07.*, #AAM.*
FROM BPCSPROF.HPOL07
JOIN BPCSPROF.#AAM ON PPRF = #AAM.AAMPRC AND PGLNO = #AAM.AAMGLN
WHERE PORD = '605400' AND PID <> 'PZ'
You're doing inner joins, so there must be a record in both #RFC and #AAM for each record in HPOL07...
Is that what you want?
If there's a matching record in #RFC or #AAM, then you'd want to use a LEFT OUTER JOIN
SELECT HPOL07.*, #RFC.*, #AAM.*
FROM BPCSPROF.HPOL07
LEFT OUTER JOIN BPCSPROF.#RFC
ON PRFC = #RFC.RFCNUM AND PPRF = #RFC.RFCPRC
AND PGLNO = #RFC.RFCGLN
LEFT OUTER JOIN BPCSPROF.#AAM
ON PPRF = #AAM.AAMPRC AND PGLNO = #AAM.AAMGLN
WHERE PORD = '605400' AND PID <> 'PZ'
This question could certainly use a table schema but my guess is that PGLNO is a different value between your two joins. If that's the case, the joins aren't going to to work because it is effectively looking for #AAM.AAMGLN = #RFC.RFCGLN in your current query. This is because both joins use the PGLNO value and would need to be the same for both join clauses.
If you want two separate results, #Charles answer should do what you want.
You can also use:
SELECT * FROM A h
LEFT JOIN B pk ON (pk.PKKONZ='010') AND (pk.PKFIRM IN (10, 20 30)) AND h.TPPALN = pk.PKPALN
LEFT JOIN C ar ON (ar.TZKONZ='010') AND (ar.TZFIRM IN (55, 56 ,57)) AND h.TPIDEN = ar.TZIDEN
WHERE ....
ORDER BY ...

Laravel query builder join using either one of two conditions

I have a complex query that I want to use either Query Builder or Eloquent (preferred) but I'm struggling with an inner join.
The inner join needs to be one of either of 2 conditions so if one fails, the other is used.
This is my original query
SELECT DISTINCT tableA.crmid, tableB.*
FROM tableB
INNER JOIN tableA ON tableA.crmid = tableB.customaccountsid
INNER JOIN tableC ON (tableC.relcrmid = tableA.crmid OR tableC.crmid = tableA.crmid)
WHERE tableA.deleted = 0 AND tableC.relcrmid = 123 AND tableC.relation_id = 186
This is my attempt at using Query Builder and I know where the problem lies. It's where I join tableC. I don't know how to use my condition there
DB::table('tableB')
->join('tableA', 'tableA.crmid', '=', 'tableB.customaccountsid')
->join('tableC', function($join) {
$join->on(DB::raw('(tableC.relcrmid = tableA.crmid OR tableC.crmid = tableA.crmid)'));
})
->where('tableA.deleted', 0)
->where('tableC.relcrmid', 3727)
->where('tableC.relation_id', 186)
->select('tableA.crmid', 'tableB.*')
Ant this is the output of the query when i output as SQL
SELECT `tableA`.`crmid`, `tableB`.*
FROM `tableB`
INNER JOIN `tableA` ON `tableA`.`crmid` = `tableB`.`customaccountsid`
INNER JOIN `tableC` ON `tableC`.`relcrmid` = (tableC.relcrmid = tableA.crmid OR tableC.crmid = tableA.crmid)
WHERE `tableA`.`deleted` = ? AND `tableC`.`relcrmid` = ? AND `tableC`.`relation_id` = ?
Just try this:
->join('tableC', function ($join){
$join->on(function($query){
$query->on('tableC.relcrmid', '=', 'tableA.crmid')
->orOn('tableC.crmid', '=', 'tableA.crmid');
});
})
It returns as in your original query:
INNER JOIN tableC ON (tableC.relcrmid = tableA.crmid OR tableC.crmid = tableA.crmid)

Simplifying where clause when a column is mutual for the tables at from clause

I would like to learn if there is any more efficient way to write the query below:
SELECT *
FROM requests srp
INNER JOIN surgeons rpsur
ON rpsur.id = srp.surgeon_id
LEFT OUTER JOIN #usersurgeons usersurgeons
ON usersurgeons.surgeon_id = srp.surgeon_id
LEFT OUTER JOIN surgeons LOsurgeons
ON usersurgeons.surgeon_id = LOsurgeons.id
LEFT OUTER JOIN provsurgeons LOprovsurgeons
ON LOprovsurgeons.id = LOsurgeons.provsurgeon_id
INNER JOIN #selectedsurgeons up
ON up.surgeon_id = rpsur.id
LEFT OUTER JOIN provsurgeons ps
ON ps.id = rpsur.provsurgeon_id
WHERE rpsur.isprimary = 0
AND usersurgeons.isprimary = 0
AND LOsurgeons.isprimary = 0
AND LOprovsurgeons.isprimary = 0
AND up.isprimary = 0
AND ps.isprimary = 0
I am not happy with the where clause here, is there any more professional way to write this, rather than adding the clauses to the join lines (such as on xx.id = yy.id and xx.isPrimary=0)??
From this query alone there are not many things that can be said. You should consider adding some more context (how do you get data into those temporary tables and the structure of %surgeons tables):
1) Select * makes almost impossible to use any index and also provides a lot of columns (Requests.*, surgeons.*, Provsurgeons.* etc.) in your final result. Return only the columns that you need.
2) If isPrimary = 0 filtering is performed often in your queries (not just this one), you can consider creating a view that fetches data filtered by isPrimary = 0. E.g. vwSurgeons, vwProvsurgeons. Then, you can just JOIN directly to the view instead of the table.
3) [already mentioned in the comments] Any condition that excludes NULL values for the OUTER JOINed table will transform the OUTER into INNER.
Instead of joining all tables and having a where clause at the end, use a derived tables only with filtered records. This way your query performance will be better.
SELECT *
FROM requests srp
INNER JOIN surgeons rpsur
ON rpsur.id = srp.surgeon_id
LEFT OUTER JOIN
(
SELECT *
FROM #usersurgeons
WHERE isprimary = 0
)usersurgeons
ON usersurgeons.surgeon_id = srp.surgeon_id
LEFT OUTER JOIN
(
SELECT *
FROM surgeons
WHERE isprimary = 0
)LOsurgeons
ON usersurgeons.surgeon_id = LOsurgeons.id
LEFT OUTER JOIN
(
SELECT *
FROM provsurgeons
WHERE isprimary = 0
)LOprovsurgeons
ON LOprovsurgeons.id = LOsurgeons.provsurgeon_id
INNER JOIN
(
SELECT *
FROM #selectedsurgeons
WHERE isprimary = 0
)up
ON up.surgeon_id = rpsur.id
LEFT OUTER JOIN
(
SELECT *
FROM provsurgeons
WHERE isprimary = 0
) ps
ON ps.id = rpsur.provsurgeon_id
WHERE rpsur.isprimary = 0