I need to express the following join condition using ActiveRecord:
SELECT ...
FROM U
LEFT OUTER JOIN F ON U.key = F.foreign_key
AND F.key = ?
WHERE ...
where ? is substituted at run time.
The following causes a SQL-syntax error:
joins("LEFT OUTER JOIN F on U.key = F.foreign_key AND F.key=?", key)
I can't seem to determine if ActiveRecord supports this 'dynamic substitution' (whatever this is called).
Adding the restriction (where("F.key=?", key)) in the WHERE clause will collapse the OUTER JOIN to a JOIN.
This syntax worked:
joins("LEFT OUTER JOIN F on U.key = F.foreign_key AND F.key=#{key}")
Related
I am fairly new to sql in general, and I am trying to work with a database which is extremely large. Now, on the website's examples, there is this query
SELECT m.chembl_id AS compound_chembl_id,
s.canonical_smiles,
r.compound_key,
NVL(TO_CHAR(d.pubmed_id),d.doi) AS pubmed_id_or_doi,
a.description AS assay_description, act.standard_type,
act.standard_relation,
act.standard_value,
act.standard_units,
act.activity_comment
FROM compound_structures s,
molecule_dictionary m,
compound_records r,
docs d,
activities act,
assays a,
target_dictionary t
WHERE s.molregno (+) = m.molregno
AND m.molregno = r.molregno
AND r.record_id = act.record_id
AND r.doc_id = d.doc_id
AND act.assay_id = a.assay_id
AND a.tid = t.tid
AND t.chembl_id = 'CHEMBL1827';
because of this (+) and this NVL I assumed it is Oracle. I am working on pgadmin4 and all my attempts at translating this after doing some research, resulted in errors. Example of my attempt and the error given bellow
SELECT m.chembl_id AS compound_chembl_id,
s.canonical_smiles,
r.compound_key,
COALESCE(CAST(d.pubmed_id AS varchar),d.doi) AS pubmed_id_or_doi,
a.description AS assay_description,
act.standard_type,
act.standard_relation,
act.standard_value,
act.standard_units,
act.activity_comment
FROM compound_structures s,
compound_records r,
docs d,
activities act,
assays a,
target_dictionary t
LEFT OUTER JOIN molecule_dictionary m ON s.molregno = m.molregno
WHERE m.molregno = r.molregno
AND r.record_id = act.record_id
AND r.doc_id = d.doc_id
AND act.assay_id = a.assay_id
AND a.tid = t.tid
AND t.chembl_id = 'CHEMBL1827';
ERROR: invalid reference to FROM-clause entry for table "s"
LINE 16: LEFT OUTER JOIN molecule_dictionary m ON s.molregno = m.molr...
^
HINT: There is an entry for table "s", but it cannot be referenced from this part of the
query.
SQL state: 42P01
Character: 492
Could someone help me?
Don't mix the old, ancient implicit joins and explicit JOIN operator:
SELECT m.chembl_id AS compound_chembl_id,
s.canonical_smiles,
r.compound_key,
COALESCE(CAST(d.pubmed_id AS varchar),d.doi) AS pubmed_id_or_doi,
a.description AS assay_description,
act.standard_type,
act.standard_relation,
act.standard_value,
act.standard_units,
act.activity_comment
FROM compound_structures s
LEFT JOIN molecule_dictionary m ON s.molregno = m.molregno
JOIN compound_records r ON m.molregno = r.molregno
JOIN docs d ON r.doc_id = d.doc_id
JOIN activities act ON r.record_id = act.record_id
JOIN assays a ON act.assay_id = a.assay_id
JOIN target_dictionary t ON a.tid = t.tid
WHERE t.chembl_id = 'CHEMBL1827';
I hope I got the direction of the outer join correct - I haven't used that Oracle syntax for decades (note that even Oracle recommends to stop using it).
But the inner join on the following tables effectively turns that outer join back into an inner join - I don't think the Oracle syntax changes that (meaning: I think that attempt on an outer join in the original query was wrong to begin with). So maybe you can simplify the LEFT JOIN to a JOIN. I am not sure if that outer join actually makes sense in the Oracle query.
Consider:
SELECT
m.chembl_id AS compound_chembl_id,
s.canonical_smiles,
r.compound_key,
COALESCE((d.pubmed_id)::text, d.doi) AS pubmed_id_or_doi,
a.description AS assay_description,
act.standard_type,
act.standard_relation,
act.standard_value,
act.standard_units,
act.activity_comment
FROM
compound_structures s
INNER JOIN molecule_dictionary m ON s.molregno = m.molregno
INNER JOIN compound_records r ON m.molregno = r.molregno
INNER JOIN docs d ON r.doc_id = d.doc_id
INNER JOIN activities act ON r.record_id = act.record_id
INNER JOIN assays a ON act.assay_id = a.assay_id
INNER JOIN target_dictionary t ON a.tid = t.tid AND t.chembl_id = 'CHEMBL1827'
Rationale:
use standard, explicit joins everywhere; old school joins have been deprecated 20 years ago!
COALESCE() is more standard than NVL()
a LEFT JOIN followed by INNER JOINs that relate to columns coming for the left table is actually equivalent to INNER JOIN
Can't figure out why I can't perform this join, I've done many like it in the past. Am I missing something?
SELECT *
FROM THB_View.PCM_PCM_BASE base
LEFT OUTER JOIN THB_View.PCM_PCM_BASE_REOCCUR rec
LEFT OUTER JOIN THB_View.ATV atv ON base.PCM_TAG = atv.ATV_OCCURRING_PCM_TAG
ON base.RECORD_KEY = rec.RECORD_KEY
WHERE
base.PCM_STATUS = 'ENROUTE'
AND rec.PCM_HRC_TAG IS NULL OR rec.PCM_HRC_TAG = ''
AND rec.PCM_EQP_TAG IS NULL OR rec.PCM_EQP_TAG = ''
The error occurs on base.PCM_TAG the 5th line in the SQL statement
Your from clause is not the typical way to write the joins. It is allowed, but this affects the scoping of the identifiers. Essentially, this is interpreted as:
from THB_View.PCM_PCM_BASE base left join
(THB_View.PCM_PCM_BASE_REOCCUR rec left join
THB_View.ATV atv
on base.PCM_TAG = atv.ATV_OCCURRING_PCM_TAG
)
on base.RECORD_KEY = rec.RECORD_KEY
Which explains why base is not recognized.
Just write the joins the standard way with the on condition right after the tables being joined:
from THB_View.PCM_PCM_BASE base left join
THB_View.PCM_PCM_BASE_REOCCUR rec
on base.RECORD_KEY = rec.RECORD_KEY left join
THB_View.ATV atv
on base.PCM_TAG = atv.ATV_OCCURRING_PCM_TAG
What is the name|type of this query? Like inner join, outer join.
SELECT a.tutorial_id, a.tutorial_author, b.tutorial_count
FROM tutorials_tbl a, tcount_tbl b
WHERE a.tutorial_author = b.tutorial_author
It's an Implicit INNER JOIN most commonly found in older code. It is synonymous with:
SELECT a.tutorial_id,
a.tutorial_author,
b.tutorial_count
FROM tutorials_tbl a
INNER JOIN tcount_tbl b ON a.tutorial_author = b.tutorial_author
which is also synonymous with just using JOIN:
SELECT a.tutorial_id,
a.tutorial_author,
b.tutorial_count
FROM tutorials_tbl a
JOIN tcount_tbl b ON a.tutorial_author = b.tutorial_author
I'm trying to pass this query to inner join, but it does not know how?
This is the query I want to use InnerJoin with these values where
SELECT
ticket.id_ticket,
ticket.id_rede,
historico.id_historico,
historico.id_ticket,
centro.id_centro,
eqpto.id_eqpto,
eqpto.nome,
centro.sigla_centro,
interface.id_interface,
interface.id_eqpto,
interface.desig,
tecnologia.descricao,
interface.id_tecnologia,
tecnologia.id_tecnologia,
eqpto.id_centro,
eqpto.id_rede
FROM
app_gpa_ticket.ticket,
app_gpa_ticket.historico,
dados_v3.centro,
dados_v3.eqpto,
dados_v3.interface,
dados_v3.tecnologia
WHERE
ticket.id_ticket = historico.id_ticket AND
centro.id_centro = eqpto.id_centro AND
eqpto.id_eqpto = interface.id_eqpto AND
eqpto.id_rede = ticket.id_rede AND
tecnologia.id_tecnologia = interface.id_tecnologia;
Thank you!
I think you are trying to go to the standard (explicit) syntax. What you need to do is take what would be your JOIN operators in the WHERE clause and move them near the table itself. What you need to know is what tables on the left (Before the INNER JOIN operator you are joining to the right (After the INNER JOIN operator)
SELECT
ticket.id_ticket,
ticket.id_rede,
historico.id_historico,
historico.id_ticket,
centro.id_centro,
eqpto.id_eqpto,
eqpto.nome,
centro.sigla_centro,
interface.id_interface,
interface.id_eqpto,
interface.desig,
tecnologia.descricao,
interface.id_tecnologia,
tecnologia.id_tecnologia,
eqpto.id_centro,
eqpto.id_rede
FROM app_gpa_ticket.ticket
INNER JOIN app_gpa_ticket.historico ON ticket.id_ticket = historico.id_ticket
INNER JOIN dados_v3.eqpto ON eqpto.id_rede = ticket.id_rede
INNER JOIN dados_v3.interface ON eqpto.id_eqpto = interface.id_eqpto
INNER JOIN dados_v3.centro ON centro.id_centro = eqpto.id_centro
INNER JOIN dados_v3.tecnologia ON tecnologia.id_tecnologia = interface.id_tecnologia
I have ran into a snag with my Linq-to-Sql.
I have a sql query that runs the way I want and usually I use Linqer to convert to Linq to see the general idea. But this time my SQL query seems to advanced for Linqer. :/
I think the problem is the INNER JOINS that are nested in the LEFT OUTER JOIN. Unfortunately I have never ran into this before and don't know how to solve it using Linq.
My SQL query looks like this:
SELECT c.[Company], c.[Name_First], c.[Name_Last], ort.[IDOriginatorRoleType],
ort.[RoleType] AS [OriginatorRoleType], o.[IDOriginator], o.[IDWork],
o.[IDContact], m.[IDMedia], m.[IDWork], m.[FileName], m.[FileNameOnDisk],
m.[DateAdded], w.[IDWork] AS [IDWork2], w.[ArticleNumber], w.[Title],
w.[FrontPageLow], w.[FrontPageLowOnDisk], w.[FrontPageHigh],
w.[FrontPageHighOnDisk]
FROM [dbo].[tblSubscriptionsWorks] AS sw
INNER JOIN [dbo].[tblWorks] AS w ON sw.[IDWork] = w.[IDWork]
LEFT OUTER JOIN [dbo].[tblMedias] AS m ON m.[IDWork] = w.[IDWork]
LEFT OUTER JOIN ([dbo].[tblOriginators] AS o
INNER JOIN [dbo].[tblOriginatorRoles] AS ors ON
o.[IDOriginatorRole] = ors.[IDOriginatorRole]
INNER JOIN [dbo].[tblOriginatorRoleTypes] AS ort ON
ors.[IDOriginatorRoleType] = ort.[IDOriginatorRoleType]
INNER JOIN [dbo].[tblContacts] AS c ON
o.[IDContact] = c.[IDContact]) ON
(o.[IDWork] = w.[IDWork]) AND (ort.[IDOriginatorRoleType] = 1)
WHERE sw.[IDWork_Subscription] = 9942
The left outer join is not a problem what I can see. You just have to divide the statement
LEFT OUTER JOIN ([dbo].[tblOriginators] AS o
INNER JOIN [dbo].[tblOriginatorRoles] AS ors ON
o.[IDOriginatorRole] = ors.[IDOriginatorRole]
INNER JOIN [dbo].[tblOriginatorRoleTypes] AS ort ON
ors.[IDOriginatorRoleType] = ort.[IDOriginatorRoleType]
INNER JOIN [dbo].[tblContacts] AS c ON
o.[IDContact] = c.[IDContact]) ON
(o.[IDWork] = w.[IDWork]) AND (ort.[IDOriginatorRoleType] = 1)
into another IQueryable list. In the example the variable db is the datacontext. Here is a suggestion to a solution:
//selects all the columns that is just in the select from the left join
var leftJoin=
(
from o in db.tblOriginators
join ors in db.tblOriginatorRoles
on o.IDOriginatorRole equals ors.IDOriginatorRole
join ort in db.tblOriginatorRoleTypes
on ors.IDOriginatorRoleType equals ort.IDOriginatorRoleType
join c in db.tblContacts
on o.IDContact equals c.IDContact
where ort.IDOriginatorRoleType==1
select new
{
o.IDWork,
c.Company,
c.Name_First,
c.Name_Last,
ort.IDOriginatorRoleType,
ort.RoleType,
o.IDOriginator,
o.IDContact
}
);
var output=(
from sw in db.tblSubscriptionsWorks
join w in db.tblWorks
on sw.IDWork equals w.IDWork
from m in db.tblMedias
.Where(x=>x.IDWork==w.IDWork).DefaultIfEmpty()
//Left join with the IQueryable list
from org in leftJoin
.Where(x =>x.IDWork==w.IDWork).DefaultIfEmpty()
where
sw.IDWork_Subscription == 9942
select new
{
org.Company,
org.Name_First,
org.Name_Last,
org.IDOriginatorRoleType,
OriginatorRoleType=org.RoleType,
org.IDOriginator,
org.IDWork,
m.IDMedia,
m.IDWork,
m.FileName,
m.FileNameOnDisk,
w.FrontPageLow,
w.FrontPageLowOnDisk,
w.FrontPageHigh,
w.FrontPageHighOnDisk
}
);