Joining on a many to many relationship with LINQ - sql

I have been tasked with converting some old SQL stored procs to LINQ for an EF migration we are doing and Im a little stumped. Given that this is a migration from an existing application the edmx was generated database first. So, I have a SQL statement that I am trying to replicate:
SELECT DISTINCT
d.DeliverySubscriptionId
, d.ContactId
, d.statementMacroId_fk
, m.Name as MacroName
, DeliveryMethod = REPLACE((SELECT DISTINCT
dm2.Name + ',' AS 'data()'
FROM
DeliverySubscription d2
JOIN
StatementMacro m2 on
d2.StatementMacroId_fk = m2.StatementMacroId
JOIN
DeliverySubscription_Method_Rel dmr2 ON
d2.DeliverySubscriptionId = dmr2.DeliverySubscriptionId_Fk
JOIN
dbo.DeliveryMethod dm2 ON
dmr2.DeliveryMethodId_Fk = dm2.DeliveryMethodId
WHERE
d.DeliveryConfigurationId_fk = #configurationId
AND
d.IsActive = 1
AND
D.DeliverySubscriptionId = D2.DeliverySubscriptionId FOR XML PATH('')) + '$', ',$', '')
FROM
DeliverySubscription d
INNER JOIN
StatementMacro m ON
d.StatementMacroId_fk = m.StatementMacroId
JOIN
DeliverySubscription_Method_Rel dmr ON
d.DeliverySubscriptionId = dmr.DeliverySubscriptionId_Fk
JOIN dbo.DeliveryMethod dm ON
dmr.DeliveryMethodId_Fk = dm.DeliveryMethodId
WHERE
d.DeliveryConfigurationId_fk = #configurationId
AND
d.IsActive = 1
In particular the part that I have having an issue with is the JOIN DeliverySubscription_Method_Rel which is a relationship table representing a many to many relationship between DeliverySubscription and DeliveryMethod.
This shows up as:
[DeliverySubscription] * ---- * [Delivery Method]
in the database diagram in the edmx. No DeliverySubscription_Method_Rel entity is created. As you can see in the SQL statement the JOIN is directly on the relationship table, but I cant seem to figure out how to replicate this in LINQ. Please help!
UPDATE:
So looking around the web I found a similar example which suggested doing something like this:
from s in Context.DeliverySubscriptions
from dm in s.DeliveryMethods
join sm in Context.StatementMacroes on s.StatementMacroId_Fk equals sm.StatementMacroId
where s.DeliveryConfigurationId_Fk == configurationId
select new DeliverySubscription_dto
{
DeliverySubscriptionId = s.DeliverySubscriptionId,
QubeContactId = s.QubeContactId,
statementMacroId_fk = s.StatementMacroId_Fk,
MacroName = sm.Name,
DeliveryMethod = dm.Name.Replace("$","").Replace(",$","")
}
...however because I still have a lot of other things to change in the application thus far I am unable to build in order to test this yet so I just wanted to run this buy you all to see if this seems correct.

That query is a beast. If you weren't having any performance problems with it, I would probably just add it to the datamodel and use linq/EF to call it.

Related

translate sql inner join into django objects.filter

I wanted to know how to translate this sql query into django's object.filter method
SELECT "accounts_customuser"."id"
FROM "accounts_customuser"
INNER JOIN "accounts_customuser_groups"
ON ("accounts_customuser"."id" == "accounts_customuser_groups"."customuser_id")
INNER JOIN "auth_group"
ON ("auth_group"."id" = "accounts_customuser_groups"."group_id")
where ("auth_group.name" IS NOT NULL)
in an accounts application I made a custom user model, there is also the group model that comes into play
in the django doc I saw an example but I would like to know how to apply it well for my case
q1 = Entry.objects.filter(headline__startswith="What")
q2 = q1.exclude(pub_date__gte=datetime.date.today())
q3 = q1.filter(pub_date__gte=datetime.date.today())
thank for any help.

Is there any way to use raw sql or i'm stuck with laravel-eloquent?

I'm trying to migrate an application developed in 2007 and add and api to it so I can easy develop and sync data with the new App I started a laravel project with the old database just to create the api the old database diagram look like this: Too many relationships and crazy polymorphic ones at that.
I want to migrate my query to laravel eloquent but I couldn't do it in time I tried to do it with eloquent but it took too much time is there any way to use raw sql like this or i'm stuck with eloquent this is my laravel code : here
the sql query looks like this
SELECT n.DOC_ID, n.TYP_ID, n.TYP_ID,
type_document.TYP_LIBELLE_AR, n.IND_ID,indication.IND_LIBELLE_AR,n.LAN_ID,
langue.LAN_LIBELLE_AR,
n.DOC_TITRE_PROPRE,
n.DOC_TITRE_COMPLEMENT,
n.DOC_TITRE_PARALLELE,
n.DOC_TITRE_ENSEMBLE,
n.DOC_NUMERO_PARTIE,
editeur.EDT_NOM_AR,
editeur.EDT_KEYWORDS,
n.DOC_LIEU_EDITION,
n.DOC_ANNEE,
n.DOC_EDITION,
periodicite.PER_LIBELLE_AR,
n.DIP_ID,
specialite.SPE_LIBELLE_AR,
n.COL_ID,
n.DOC_NUM,
n.COL_NUMERO,
n.COT_NOTICE,
n.SCL_ID,
n.SCL_NUMERO,
n.DOC_NBR_UNITE,
n.DOC_ILLUSTRATION,
n.DOC_FORMAT,
n.DOC_MATERIEL,
n.DOC_ISBN,
n.DOC_ISSN,
n.DOC_NBR_EXEMPLAIRE,
n.STA_ID,
n.REL_VOLUME,
n.PAY_ID,
n.DOC_AGENCE,
n.DOC_PRET_INTERNE,
n.DOC_PRET_EXTERNE,
n.DOC_KEYWORDS,
n.CREATE_DATE,
n.UPDATE_DATE,
statut_notice.STA_LIBELLE_AR,
notice_auteur.VED_ID,
notice_auteur.FON_ID,
notice_auteur.AUT_TYPE,
GROUP_CONCAT(DISTINCT vmath.VED_NOM) AS mats,
vmath.VED_KEYWORDS,
GROUP_CONCAT( DISTINCT vauth.VED_NOM) AS auths,
vauth.VED_KEYWORDS,
GROUP_CONCAT( DISTINCT notice_exemplaire.EXP_COTE) AS examp_cote,
GROUP_CONCAT( DISTINCT notice_exemplaire.LOC_ID) AS exmp_location
FROM notice n
INNER JOIN editeur ON editeur.EDT_ID =n.EDT_ID
INNER JOIN type_document ON type_document.TYP_ID = n.TYP_ID
INNER JOIN langue ON langue.LAN_ID = n.LAN_ID
INNER JOIN statut_notice ON statut_notice.STA_ID = n.STA_ID
INNER JOIN indication ON indication.IND_ID = n.IND_ID
INNER JOIN notice_exemplaire ON n.DOC_ID = notice_exemplaire.DOC_ID
LEFT JOIN specialite ON n.SPE_ID = specialite.SPE_ID
LEFT JOIN periodicite ON periodicite.PER_ID = n.PER_ID
INNER JOIN notice_auteur ON n.DOC_ID = notice_auteur.DOC_ID
INNER JOIN vedette vauth ON notice_auteur.VED_ID = vauth.VED_ID
LEFT JOIN notice_matiere ON n.DOC_ID = notice_matiere.DOC_ID
LEFT JOIN vedette vmath ON notice_matiere.VED_ID = vmath.VED_ID
GROUP BY n.DOC_ID
1:
For something like this you can use DB::select('YOUR-QUERY').
DB::select('...') calls select() on the underlying Connection class so it's not the same as using DB::table('...')->select('...') which is calling the select method on the Builder class.
For more information on running raw queries you can refer to the documentation.

I need to convert to codeigniter3 active record syntax

I need to join main (4-5) tables and get the latest from the inner join table to get the project current status.
investor have many investments
investments have many investment_details
investment_details has many status through project status
Select
siv.company_name
, siv.full_name
, si.permit_number
, si.project_name
, sid.investment_detailed_id
, sis.project_status_id
, sps.project_status_name
From sma_investors siv
Join sma_investments si
On siv.investor_id = si.investment_id
Join sma_investment_details sid
On si.investment_id = sid.investment_id
Inner Join sma_investment_status sis
On sis.investment_status_id = (
Select investment_status_id
From sma_investment_status s
Where s.investment_detailed_id = sid.investment_detailed_id
Order BY investment_status_id DESC LIMIT 1)
Join sma_project_status sps
On sis.project_status_id = sps.project_status_id
This works fine but I can't convert it the CI3.
There is no advantage to using Query Builder (QB) unless you need parts of the query to be written differently due to some condition. QB is also useful if you want user inputs to be automatically escaped. Otherwise, you simply run a whole lot of extra code that leads to the exact same SQL statement string you already have.
In your case, the sub-select will make the conversion even more difficult to accomplish and add a lot of extra code to be executed.
My advice is to keep it simple and use db->query(), e.g.
$sql = "Select siv.company_name, siv.full_name, si.permit_number, si.project_name
, sid.investment_detailed_id, sis.project_status_id, sps.project_status_name
From sma_investors siv
Join sma_investments si On siv.investor_id = si.investment_id
Join sma_investment_details sid On si.investment_id = sid.investment_id
Inner Join sma_investment_status sis On sis.investment_status_id = (
Select investment_status_id From sma_investment_status s
Where s.investment_detailed_id = sid.investment_detailed_id
Order BY investment_status_id DESC LIMIT 1)
Join sma_project_status sps On sis.project_status_id = sps.project_status_id";
$query = $this->db->query($sql);
if(! $query) // might be false if query fails
{
return null;
}
return $query->row(); // one row of data
I finally come up with my own solution and stick to the QB codding standard and it works as i expected
$q = $this->db->select('*')
->from('investors')
->join('investments', `enter code here`'investors.investor_id=investments.investment_id')
->join('investment_details as sid', 'investments.investment_id=sid.investment_id')
->join('investment_status', 'investment_status.investment_status_id=(select '.$this->db->dbprefix('investment_status').'.investment_status_id from '.$this->db->dbprefix('investment_status').' where '.$this->db->dbprefix('investment_status').'.investment_detailed_id=sid.investment_detailed_id order by '.$this->db->dbprefix('investment_status').'.investment_status_id Desc limit 1)', 'inner')
->join('project_status', 'investment_status.project_status_id=project_status.project_status_id')
->where('sid.company_type_id', 1)
->order_by('investments.investment_id', 'desc')
->limit(5)
->get();

SQL Server : multi-join with tuple IN clause

I'm trying to join 4 tables that have a somewhat complex relationship. Because of where this will be used, it needs to be contained in a single query, but I'm having trouble since the primary query and the IN clause query both join 2 tables together and the lookup is on two columns.
The goal is to input a SalesNum and SalesType and have it return the Price
Tables and relationships:
sdShipping
SalesNum[1]
SalesType[2]
Weight[3]
sdSales
SalesNum[1]
SalesType[2]
Zip[4]
spZones
Zip[4]
Zone[5]
spPrices
Zone[5]
Price
Weight[3]
Here's my latest attempt in T-SQL:
SELECT
spp.Price
FROM
spZones AS spz
LEFT OUTER JOIN
spPrices AS spp ON spz.Zone = spp.Zone
WHERE
(spp.Weight, spz.Zip) IN (SELECT ship.Weight, sales.Zip
FROM sdShipping AS ship
LEFT OUTER JOIN sdSales AS sales ON sales.SalesNum = ship.SalesNum
AND sales.SalesType = ship.SalesType
WHERE sales.SalesNum = (?)
AND ship.SalesType = (?));
SQL Server Management Studio says I have an error in my syntax near ',' (appropriately useless error message). Does anybody have any idea whether this is even allowed in Microsoft's version of SQL? Is there perhaps another way to accomplish it? I've seen the multi-key IN questions answered on here, but never in the case where both sides require a JOIN.
Many databases do support IN on tuples. SQL Server is not one of them.
Use EXISTS instead:
SELECT spp.Price
FROM spZones spz LEFT OUTER JOIN
spPrices spp
ON spz.Zone = spp.Zone
WHERE EXISTS (SELECT 1
FROM sdShipping ship LEFT JOIN
sdSales sales
ON sales.SalesNum = ship.SalesNum AND
sales.SalesType = ship.SalesType
WHERE spp.Weight = ship.Weight AND spz.Zip = sales.Zip AND
sales.SalesNum = (?) AND
ship.SalesType = (?)
);

Help converting multi DB SQL Query to LINQ

I have the below SQL Query, which returns what I expect, and I would LIKE to accomplish the same thing in LINQ but so far my results have been less then spectacular. The major hurdle, as I see it, is that the data is coming from 3 separate DB's. I was able to accomplish this in LINQ but it is extremely slow, see here.
So, with out further ado, here it is, with the hardcoded Guid() being the only exception as that gets passed in:
SELECT en.ClientID, p.LastName, p.FirstName, NurseName = dm2.FirstName + ' ' + dm2.LastName, SocialWorkerName = dm.FirstName + ' ' + dm.LastName, en.EnrollmentDate, en.DisenrollmentDate, ESWorkerName = sw.FirstName + ' ' + sw.LastName, sw.Phone
FROM CMO.dbo.tblCMOEnrollment en
LEFT OUTER JOIN CMO.dbo.tblSupportWorker sw
ON en.EconomicSupportWorkerID = sw.SupportWorkerID
INNER JOIN Connect.dbo.tblPerson p
ON en.ClientID = p.PersonID
LEFT OUTER JOIN aspnetdb.dbo.tblDemographics dm
ON en.CMOSocialWorkerID = dm.UserID
LEFT OUTER JOIN aspnetdb.dbo.tblDemographics dm2
ON en.CMONurseID = dm2.UserID
WHERE (en.CMOSocialWorkerID = '060632EE-BE09-4057-B17B-2D0190D0FF74'
OR
en.CMONurseID = '060632EE-BE09-4057-B17B-2D0190D0FF74')
AND (en.DisenrollmentDate IS NULL
OR
en.DisenrollmentDate > GetDate())
ORDER BY en.DisenrollmentDate, p.LastName
Since you want to issue 1 query, you should only use 1 datacontext. Add views to one of the databases to represent the other databases tables, then add it all to one LinqToSqlClasses file.
If you can't modify any of the three databases, create a fourth database with views to the other three.