Generate FULL JOIN with LinqToSQL - linq-to-sql

I have this linq query :
(from rapportBase in New_RapportReferencementBases
join rapportExtensionAll in New_RapportReferencementExtensionBases on rapportBase.New_RapportReferencementId equals rapportExtensionAll.New_RapportReferencementId into jointureRapportExtension
from rapportExtension in jointureRapportExtension.DefaultIfEmpty()
join packExtensionAll in New_PackExtensionBases on rapportExtension.New_PackId equals packExtensionAll.New_PackId into jointurePackExtension
from packExtension in jointurePackExtension.DefaultIfEmpty()
join packBaseAll in New_PackBases on packExtension.New_PackId equals packBaseAll.New_PackId into jointurePackBase
from packBase in jointurePackBase.DefaultIfEmpty()
join domaineBaseAll in New_DomaineBases on packExtension.New_DomaineId equals domaineBaseAll.New_DomaineId into jointureDomaineBase
from domaineBase in jointureDomaineBase.DefaultIfEmpty()
join domaineExtensionAll in New_DomaineExtensionBases on domaineBase.New_DomaineId equals domaineExtensionAll.New_DomaineId into jointureDomaineExtension
from domaineExtension in jointureDomaineExtension.DefaultIfEmpty()
join compteBaseAll in AccountBases on domaineExtension.New_AccountId equals compteBaseAll.AccountId into jointureCompteBase
from compteBase in jointureCompteBase.DefaultIfEmpty()
join compteExtensionAll in AccountExtensionBases on compteBase.AccountId equals compteExtensionAll.AccountId into jointureCompteExtension
from compteExtension in jointureCompteExtension.DefaultIfEmpty()
select rapportBase)
which generate :
SELECT [t0].[New_RapportReferencementId], [t0].[CreatedOn], [t0].[CreatedBy], [t0].[ModifiedOn], [t0].[ModifiedBy], [t0].[OwningUser], [t0].[OwningBusinessUnit], [t0].[statecode] AS [Statecode], [t0].[statuscode] AS [Statuscode], [t0].[DeletionStateCode], [t0].[VersionNumber], [t0].[ImportSequenceNumber], [t0].[OverriddenCreatedOn], [t0].[TimeZoneRuleVersionNumber], [t0].[UTCConversionTimeZoneCode]
FROM [New_RapportReferencementBase] AS [t0]
LEFT OUTER JOIN [New_RapportReferencementExtensionBase] AS [t1] ON [t0].[New_RapportReferencementId] = [t1].[New_RapportReferencementId]
LEFT OUTER JOIN [New_PackExtensionBase] AS [t2] ON [t1].[New_PackId] = ([t2].[New_PackId])
LEFT OUTER JOIN [New_PackBase] AS [t3] ON [t2].[New_PackId] = [t3].[New_PackId]
LEFT OUTER JOIN [New_DomaineBase] AS [t4] ON [t2].[New_DomaineId] = ([t4].[New_DomaineId])
LEFT OUTER JOIN [New_DomaineExtensionBase] AS [t5] ON [t4].[New_DomaineId] = [t5].[New_DomaineId]
LEFT OUTER JOIN [AccountBase] AS [t6] ON [t5].[New_AccountId] = ([t6].[AccountId])
LEFT OUTER JOIN [AccountExtensionBase] AS [t7] ON [t6].[AccountId] = [t7].[AccountId]
But I want to generate :
SELECT [t0].[New_RapportReferencementId], [t0].[CreatedOn], [t0].[CreatedBy], [t0].[ModifiedOn], [t0].[ModifiedBy], [t0].[OwningUser], [t0].[OwningBusinessUnit], [t0].[statecode] AS [Statecode], [t0].[statuscode] AS [Statuscode], [t0].[DeletionStateCode], [t0].[VersionNumber], [t0].[ImportSequenceNumber], [t0].[OverriddenCreatedOn], [t0].[TimeZoneRuleVersionNumber], [t0].[UTCConversionTimeZoneCode]
FROM [New_RapportReferencementBase] AS [t0]
FULL OUTER JOIN [New_RapportReferencementExtensionBase] AS [t1] ON [t0].[New_RapportReferencementId] = [t1].[New_RapportReferencementId]
FULL OUTER JOIN [New_PackExtensionBase] AS [t2] ON [t1].[New_PackId] = ([t2].[New_PackId])
FULL OUTER JOIN [New_PackBase] AS [t3] ON [t2].[New_PackId] = [t3].[New_PackId]
FULL OUTER JOIN [New_DomaineBase] AS [t4] ON [t2].[New_DomaineId] = ([t4].[New_DomaineId])
FULL OUTER JOIN [New_DomaineExtensionBase] AS [t5] ON [t4].[New_DomaineId] = [t5].[New_DomaineId]
FULL OUTER JOIN [AccountBase] AS [t6] ON [t5].[New_AccountId] = ([t6].[AccountId])
FULL OUTER JOIN [AccountExtensionBase] AS [t7] ON [t6].[AccountId] = [t7].[AccountId]
In other word, i want to generate full outer join for this query and not just left.
someone know how to do this in a simple way ?
thanks

There isn't a Full Outer Join in Linq. You have to do two left joins and concat them together. Here's some pseudocode that looks like linq:
var foj =
(from l in left
join r in right on l.Id equals r.Id into g
from r in g.DefaultIfEmpty()
select new { l, r })
.Concat
(from r in right
join l in left on r.Id equals l.Id into g
from l in g.DefaultIfEmpty()
where l == null
select new { l, r });
Probably be better to push this logic into a stored procedure if you're planning on using Linq to Sql.

See this post from the VB Team:
http://blogs.msdn.com/vbteam/archive/2008/02/12/converting-sql-to-linq-part-9-full-outer-join-bill-horst.aspx
Looks a little verbose.
Otherwise, there may be a way to achieve what you want using Foreign Keys and the Union operator.

Sadly I saw that before but i wanted to be sure.
The thing we did is to do it in a stored procedure and access it via linqtosql method.
then we map table result, like linqtosql do, using grouping to obtain collection of enties link to another entity.
for example, if we have an account with some contacts link to it. We request all contact with for each of them the account with a full join and them group on account id to obtain list of contact of each.
It work very well but it would be better if linqtosql was able to generate full join....

Related

Mysql view are very slow

My mysql view is really slow in thousands of data how can we improve this functionality?
While fetch this view in 10000s data then it takes more than 30 sec. how could we revise this view table?
SELECT
i.jo_in_id,
j.*,
i.jo_in_week_number,
i.jo_in_client_ref_no,
i.cl_id AS jo_in_cl_id,
c.cl_short_name,
c.cl_business_name,
m.me_first_name,
m.me_last_name,
m.me_mobile,
sk.sk_name,
sk.sk_ticketed,
ti.ti_id,
ta.ta_name,
u.un_id,
u.un_from,
u.un_to,
v.ve_name,
mp.vmp_name,
r.vr_name
FROM
jo_2_no j2n,
jo_in_numbers i,
jobs j
LEFT JOIN venues_new v ON j.ve_id = v.ve_id
LEFT JOIN venues_meeting_place mp ON j.vmp_id = mp.vmp_id
LEFT JOIN venues_rooms r ON j.vr_id = r.vr_id
LEFT JOIN clients c ON j.cl_id = c.cl_id
LEFT JOIN members m ON j.me_id = m.me_id
LEFT JOIN skills sk ON j.sk_id = sk.sk_id
LEFT JOIN tasks ta ON j.ta_id = ta.ta_id
LEFT JOIN crew_tickets ti ON j.sk_id = ti.sk_id AND j.me_id = ti.me_id AND j.jo_time_off < ti.ti_expire
LEFT JOIN unavailability u ON j.me_id = u.me_id AND ((j.jo_time_on BETWEEN u.un_from AND u.un_to) OR (j.jo_time_on BETWEEN u.un_from AND u.un_to))
WHERE
j.jo_id = j2n.jo_id
AND j2n.jo_in_numbers_id = i.jo_in_id
AFTER user EXPLAIN SELECT following is the output
In your EXPLAIN, I see that your joined tables ti and u are read with table-scans (type: ALL). This is probably the biggest problem for your performance.
You should make sure you have the following indexes created:
ALTER TABLE crew_tickets ADD KEY (sk_id, me_id, ti_expire);
ALTER TABLE unavailability ADD KEY (me_id, un_from, un_to);
That should help the joins to those tables work with index lookups instead of table-scans. I think they'll be accessed as covering indexes, too.
Also, please don't use the outdated "comma-joins." Especially do not mix both styles. It will bite you when you get surprised by the order of precedence between comma-joins and JOIN operators. See examples in Can someone help explain why not using a SQL JOIN is bad practice and wrong? or Error on JOIN mysql.
Write your joins this way:
FROM jo_2_no j2n
INNER JOIN jo_in_numbers i ON j2n.jo_in_numbers_id = i.jo_in_id
INNER JOIN jobs j ON j.jo_id = j2n.jo_id
LEFT JOIN venues_new v ON j.ve_id = v.ve_id
LEFT JOIN venues_meeting_place mp ON j.vmp_id = mp.vmp_id
LEFT JOIN venues_rooms r ON j.vr_id = r.vr_id
LEFT JOIN clients c ON j.cl_id = c.cl_id
LEFT JOIN members m ON j.me_id = m.me_id
LEFT JOIN skills sk ON j.sk_id = sk.sk_id
LEFT JOIN tasks ta ON j.ta_id = ta.ta_id
LEFT JOIN crew_tickets ti ON j.sk_id = ti.sk_id
AND j.me_id = ti.me_id AND j.jo_time_off < ti.ti_expire
LEFT JOIN unavailability u ON j.me_id = u.me_id
AND j.jo_time_on BETWEEN u.un_from AND u.un_to
I removed the redundant term in the join condition for u. The optimizer might eliminate that logic, but why make it work so hard?

How to filter not null values in mysql query?

I have the following mysql query. Joins are done only on FKs.
select le.lexicalentryid, def.senseid, def.definitionid, frwf.writtenForm, trdef.writtentext, frwf.wordformid, frwf.phoneticForm, le.partofspeech, le.lexiconid
from formrepresentation_wordform frwf
left join wordform wf on wf.wordformid = frwf.wordformid
left join lexicalentry le on le.lexicalentryid = wf.lexicalentryid
left join sense se on se.lexicalentryid = le.lexicalentryid
left join definition def on def.senseid = se.senseid
left join textrepresentation_definition trdef on trdef.definitionid = def.definitionid
where frwf.languageidentifier like '%deu%'
I get the following results (I show only the first 4)
I would like to get rid of the null values. They appear because for the same definitionid I have a single written form. When this happens I know I have to take the missing words from other table so now, I have to clear off the nulls.
I tried to add to the where clause frwf.writtenForm is not null, but with no success (all the writtenform column became blank)
I have managed to create the query:
SELECT frl.writtenForm, frl.languageIdentifier, le.partOfSpeech, wf.idx, frw.phoneticForm, se._index, trd.writtenText
FROM FormRepresentation_Lemma frl
JOIN LexicalEntry le ON (frl.lemmaId = le.lemmaId)
JOIN WordForm wf ON (le.lexicalEntryId = wf.lexicalEntryId)
JOIN FormRepresentation_WordForm frw ON (frw.wordFormId = wf.wordFormId)
JOIN Sense se ON (le.lexicalEntryId = se.lexicalEntryId)
JOIN Definition de ON (se.senseId = de.senseId)
JOIN TextRepresentation_Definition trd ON (de.definitionId = trd.definitionId)
WHERE frl.languageidentifier like '%deu%'
It was this table that I didn't take into account FormRepresentation_Lemma that contains link entries for null values
you need an inner join
select le.lexicalentryid, def.senseid, def.definitionid, frwf.writtenForm, trdef.writtentext, frwf.wordformid, frwf.phoneticForm, le.partofspeech, le.lexiconid
from formrepresentation_wordform frwf
inner join wordform wf on wf.wordformid = frwf.wordformid
left join lexicalentry le on le.lexicalentryid = wf.lexicalentryid
left join sense se on se.lexicalentryid = le.lexicalentryid
left join definition def on def.senseid = se.senseid
left join textrepresentation_definition trdef on trdef.definitionid = def.definitionid
where frwf.languageidentifier like '%deu%'
and possibly the other joins too. Inner join states that both tables must have a matching entry to be fetched.

Need some assistance with a complex JOIN is SQL Query

Take a look at these tables
It's simple: Venue contains country_ID which is an FK in Society_Territory where we will find a society_ID which is an FK of Society. I have a Venue_ID during the query and my objective is to get the Society_Name but there is a twist but first lets just get the Society_Name
In the following query only look at JOINS and in there I am gonna add comments with this // prefix
SELECT
uuid()AS `UUID`,
`pc`.`PRSClaimID` AS `prsclaimid`,
`a`.`LoginName` AS `loginname`,
`a`.`BandName` AS `bandname`,
`smartistdetails`.`LoginName` AS `createdbyloginname`,
`Society`.`Society_Name` AS societyName
count(
`smliveclaims`.`LiveclaimsID`
)AS `gigcount`
FROM `smprsliveclaimlink`
JOIN `smliveclaims` ON `smprsliveclaimlink`.`fkLiveClaimID` = `smliveclaims`.`LiveclaimsID`
// Here I have the Venue_ID from smliveclaims so i starting moving towards society name
JOIN Venue ON `smliveclaims`.fk_venueId = Venue.Venue_ID
JOIN Society_Territory ON Venue.Country_ID = Society_Territory.Country_ID
JOIN Society ON Society_Territory.Society_Id = Society.Society_ID
// Now from Society i can select the Society_Name which i am already doing in the query above
JOIN `smartistdetails` `a`
JOIN `smprsclaims` `pc` ON `a`.`ArtistID` = `pc`.`fkArtistID`
JOIN `smcategories` ON `pc`.`FK_CategoryID` = `smcategories`.`Id`
JOIN `smcategoriestype` ON `smcategories`.`fk_CategoryTypeId` = `smcategoriestype`.`Id`
JOIN `smartistdetails` ON `pc`.`CreatedBy` = `smartistdetails`.`ArtistID` AND `smprsliveclaimlink`.`fkPRSClaimID` = `pc`.`PRSClaimID`
GROUP BY
`a`.`LoginName`,
`a`.`BandName`,
`smcategories`.`Id`,
`smcategoriestype`.`CategoryType`,
`smartistdetails`.`LoginName`
All is cool till here. Now here is the TWIST
I will have Country_IDs in Venue which will not be in Society_Territory. And I still want to select them and instead of showing and actual Society_Name want to show a word such as "Other"
use a LEFT OUTER JOIN when you link VENUE with SOCIETY_TERRITORY and so on when you link SOCIETY_TERRITORY with SOCIETY
Pay attention: When you use a LEFT OUTER JOIN all tables depends by its must be linked with other LEFT OUTER JOIN because if you use INNER JOIN you cancel di effects on LEFT.
Edit:
SELECT
uuid()AS `UUID`,
`pc`.`PRSClaimID` AS `prsclaimid`,
`a`.`LoginName` AS `loginname`,
`a`.`BandName` AS `bandname`,
`smartistdetails`.`LoginName` AS `createdbyloginname`,
coalesce(`Society`.`Society_Name`, 'Other') AS societyName
count(`smliveclaims`.`LiveclaimsID`)AS `gigcount`
FROM `smprsliveclaimlink`
JOIN `smliveclaims`
ON `smprsliveclaimlink`.`fkLiveClaimID` = `smliveclaims`.`LiveclaimsID`
// Here I have the Venue_ID from smliveclaims so i starting moving towards society name
JOIN Venue ON `smliveclaims`.fk_venueId = Venue.Venue_ID
LEFT OUTER JOIN Society_Territory ON Venue.Country_ID = Society_Territory.Country_ID
LEFT OUTER JOIN Society ON Society_Territory.Society_Id = Society.Society_ID
// Now from Society i can select the Society_Name which i am already doing in the query above
JOIN `smartistdetails` `a`
JOIN `smprsclaims` `pc` ON `a`.`ArtistID` = `pc`.`fkArtistID`
JOIN `smcategories` ON `pc`.`FK_CategoryID` = `smcategories`.`Id`
JOIN `smcategoriestype` ON `smcategories`.`fk_CategoryTypeId` = `smcategoriestype`.`Id`
JOIN `smartistdetails` ON `pc`.`CreatedBy` = `smartistdetails`.`ArtistID` AND `smprsliveclaimlink`.`fkPRSClaimID` = `pc`.`PRSClaimID`
GROUP BY
`a`.`LoginName`,
`a`.`BandName`,
`smcategories`.`Id`,
`smcategoriestype`.`CategoryType`,
`smartistdetails`.`LoginName`
All your JOINs are INNER JOINs. The INNER keyword is optional in MySQL and frequently omitted (as in your example). Use a LEFT OUTER JOIN where required and amend your SELECT clause to include something like "COALESCE(Society_Name,'Other') Society_Name"

Convert this SQL to HQL? (left join with values instead of columns)

I'm trying to convert this SQL to HQL, but I found no way to do that left join.
SELECT
mdcs_causa.id_causa,
usuarios.ds_usuario,
usuarios.setor,
empresas.ds_empresa,
itens_controle.id_item_controle,
itens_controle.ds_item,
itens_controle.ds_indicador,
itens_controle.ds_cliente,
itens_controle.desdobramento,
itens_controle.auxiliar,
itens_controle.bmk_nome,
itens_controle.bmk_vlr,
m.status,
m.medido,
m.medicao,
m.fca,
m.am_cronico,
m.ac_cronico,
m.ap_cronico,
m.id_medicoes as idmedicao,
itens_controle.prioridade
FROM
mdcs
INNER JOIN mdcs_causa
ON mdcs.id_mdc = mdcs_causa.id_mdc
INNER JOIN itens_controle
ON mdcs_causa.Id_Item_Controle = itens_controle.id_item_controle
INNER JOIN usuarios
ON usuarios.id_usuario = itens_controle.id_usuario
INNER JOIN empresas
ON empresas.id_empresa = usuarios.id_cliente_tabela
LEFT JOIN medicoes m
ON (
itens_controle.id_item_controle = m.id_item_controle
and
m.nm_ano = 2013
and
m.nm_periodo = 2
and
mdcs_causa.id_mdc = mdcs.id_mdc
)
WHERE
mdcs.id_mdc = 5077
I thought I could put the nm_ano and nm_periodo conditions in the where clause, with an OR to m.id_item_controle is null but this OR condition didn't seem to work, even in SQL.
Another approach was to left join a sub query. That worked in SQL, but I think HQL doesn't support that.
It can be done with with keyword:
...
left join itens_controle.medicoes m with (m.nm_ano = 2013 and m.nm_periodo = 2 and mdcs_causa.id_mdc = mdcs.id_mdc)
where mdcs.id_mdc = 5077
Instead of explicit values you should supply them as arguments.
Read this in this pdf left join is used
as below:
Query getEBills =session.createQuery( session.createQuery( from " EBill ebill EBill
ebill
left join ebill.accountTransaction where
ebill.balance > 500";
Li li f l bi i li () ist listOfRowValues = getDebitTransactions.list();
for (Object[] singleRowValues : listOfRowValues) {
// pull off the EBill // pull off the EBill
EBill ebill = (EBill)singleRowValues[0];
I dont have any experience in HQL, i have pasted what i have found for you. hope this will help you in any way.

Using an IF Statement in MySQL

I have the below SQL statement. What I would like to do is include an IF statement to cover the possibility of one of the columns returning a 0 or blank result, there are no 0 ID's. In this case, I'm trying to cover the possibility of the magez_cfv_nations result possibly returning a zero or blank result.
SELECT c.clan_name, n.nation_name,
CONCAT(r.rarity_shorthand, " - ", r.rarity_name) AS rarity_text,
t.trigger_name, s.skill_name
FROM `magez_cfv_cards` AS cards
JOIN `magez_cfv_clans` c ON cards.clan_id = c.clan_id
JOIN `magez_cfv_nations` n ON cards.nation_id = n.nation_id
JOIN `magez_cfv_rarity` r ON cards.rarity_id = r.rarity_id
JOIN `magez_cfv_trigger` t ON cards.trigger_id = t.trigger_id
JOIN `magez_cfv_skills` s ON cards.skill_id = s.skill_id
You need a LEFT JOIN
The LEFT JOIN keyword returns all rows from the left table
(table_name1), even if there are no matches in the right table
Try this
SELECT c.clan_name, n.nation_name,
CONCAT(r.rarity_shorthand, " - ", r.rarity_name) AS rarity_text,
t.trigger_name, s.skill_name
FROM `magez_cfv_cards` AS cards
JOIN `magez_cfv_clans` c ON cards.clan_id = c.clan_id
LEFT JOIN `magez_cfv_nations` n ON cards.nation_id = n.nation_id
JOIN `magez_cfv_rarity` r ON cards.rarity_id = r.rarity_id
JOIN `magez_cfv_trigger` t ON cards.trigger_id = t.trigger_id
JOIN `magez_cfv_skills` s ON cards.skill_id = s.skill_id
the function you should use is IIF() and its syntax is
IIF([condition],[if true],[if false])