Help converting multi DB SQL Query to LINQ - sql

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.

Related

MS access using case in transform pivot

I'm trying to print a schedule using a query in access. The problem is when nobody is scheduled for a task the field is left blank. The problem is when nobody is scheduled for a task for the whole duration of the schedule since nobody is assigned for this task some referencing get borked. So my question is can I use a simple CASE in my query to switch a null value on Responsable.ResponsableAbrege for something like ' ' or 'N/A' or am I looking at it from the wrong angle? Here is the code :
TRANSFORM First(Responsable.ResponsableAbrege) AS PremierDeResponsableAbrege
SELECT wCalendrier.Entite, Entite.DescriptionAbrege, Tache.Tache, Fonction.Abréviation, Module.Module, Fonction.NoFonction, Tache.NoTache, First(wCalendrier.PremierResponable) AS PremierDePremierResponable
FROM RecupererResponsable, Fonction INNER JOIN ([Module] INNER JOIN (Équipe INNER JOIN (((wCalendrier INNER JOIN Tache ON wCalendrier.NoTache = Tache.NoTache) INNER JOIN Responsable ON wCalendrier.NoResponsable = Responsable.NoResponsable) INNER JOIN Entite ON wCalendrier.Entite = Entite.Entite) ON (Équipe.NoÉquipe = Responsable.Equipe) AND (Équipe.NoÉquipe = Responsable.Equipe)) ON Module.NoModule = Tache.Module) ON Fonction.NoFonction = Tache.Fonction
GROUP BY wCalendrier.Entite, Entite.DescriptionAbrege, Tache.Tache, Fonction.Abréviation, Module.Module, Fonction.NoFonction, Tache.NoTache
PIVOT "D" & [Sequence] In ("D1","D2","D3","D4","D5","D6","D7","D8","D9","D10","D11","D12","D13","D14","D15");
In MS Access SQL instead of CASE you should use either IIF or switch
iif(isnull(FIRST(Responsable.ResponsableAbrege)),'N/A', FIRST(Responsable.ResponsableAbrege))

Searching in SQL per POST-Variable in joined Table

I tried to solve this for some time and didn't come to a solution.
I read from a table filled with Mobile Devices and list them and give the user the possibilty to search the list per Movile Device Name and Username.
This is my Code:
SELECT
*
FROM
tbl_mobdev
LEFT JOIN
tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN
tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN
tbl_user ON tbl_user.id = mobdev_user
WHERE
CONCAT(tbl_marke.marke_name,' ',tbl_mobdev_type.mobdev_type_bezeichnung) LIKE '%".$_POST['marke_name']."%'
AND
CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
AND
mobdev_aktiv = '1'
ORDER BY
".$_GET['sort']." ".$_GET['sort2']."
Everything works as intended as long as tbl_mobdev.mobdev_user contains an User-ID, while table-rows that doesn't contain an User-ID are left out.
Any Solutions for this?
Edit: The solution of putting the "filter" in the LEFT JOIN for tbl_user doesn't work. An SQL like the following results in every row will be shown.
If the LIKE contains something only the not matching results will not be joined, the row doesn't get filtered.
SELECT mobdev_id, mobdev_type_bezeichnung, marke_name, tbl_user.name AS user_name, tbl_user.vorname AS user_vorname
FROM tbl_mobdev
LEFT JOIN tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN tbl_user ON tbl_user.id = mobdev_user
AND CONCAT( tbl_user.name, ' ', tbl_user.vorname ) LIKE '%%'
WHERE CONCAT( tbl_marke.marke_name, ' ', tbl_mobdev_type.mobdev_type_bezeichnung ) LIKE '%%'
AND mobdev_aktiv = '1'
ORDER BY marke_name ASC
LIMIT 0 , 30
Edit2: Setting the SQL to the following didn't changed the behavior.
SELECT mobdev_id, mobdev_type_bezeichnung, marke_name, tbl_user.name AS user_name, tbl_user.vorname AS user_vorname
FROM tbl_mobdev
LEFT JOIN tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN tbl_user ON tbl_user.id = mobdev_user
AND CONCAT( tbl_user.name, ' ', tbl_user.vorname ) LIKE '%G%'
WHERE CONCAT( tbl_marke.marke_name, ' ', COALESCE( tbl_mobdev_type.mobdev_type_bezeichnung, '' ) ) LIKE '%%'
AND mobdev_aktiv = '1'
ORDER BY marke_name ASC
LIMIT 0 , 30
Rows without matching $_POST['user'] still aren't filtered out.
I uploaded an example picture of the behavior with blurred out names, the left picute is a Select without any filter, right pictura is a Select with an actual Username (Blurred out, but its the exact same name as in mobdev_id '3'.
http://fs5.directupload.net/images/160404/tmdbyzws.png
As you can see, the other five rows are still there, just without the joins. I want them to be gone completely, because they are not matching the filter.
Edit3: Well, i made it now...sadly in a pretty dirty way using PHP. I just leave the code here, if someone comes up with a better solution for this please let me know.
$query = "
SELECT
mobdev_id,
mobdev_type_bezeichnung,
marke_name,
tbl_user.name AS user_name,
tbl_user.vorname AS user_vorname
FROM
tbl_mobdev
LEFT JOIN
tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN
tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN
tbl_user ON tbl_user.id = mobdev_user
WHERE
CONCAT(tbl_marke.marke_name,' ',tbl_mobdev_type.mobdev_type_bezeichnung) LIKE '%".$_POST['marke_name']."%'
";
if($_POST['user'])
{
$query .= "
AND
CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
";
}
$query .= "
AND
mobdev_aktiv = '1'
ORDER BY
".$_GET['sort']." ".$_GET['sort2']."
";
The problem is in the line
CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
Your LEFT JOIN on tbl_user will allow the main query to return independent of whether there's a value in that row. However, that particular WHERE clause line effectively overrides that; if tbl_user.name or tbl_user.vorname is null, the result will always be false.
If I need to do something like that, I'll often put the test into the ON clause of the JOIN statement. That way it filters the JOINed table where it exists, but doesn't cause problems where it doesn't.
Example query text that should ensure tbl_user gets filtered when required but not when nothing's specified -
SELECT
md.mobdev_id,
mdt.mobdev_type_bezeichnung,
m.marke_name,
u.name AS user_name,
u.vorname AS user_vorname
FROM
tbl_mobdev md
LEFT JOIN tbl_mobdev_type mdt
ON mdt.mobdev_type_id = md.mobdev_type
LEFT JOIN tbl_marke m
ON m.marke_id = mdt.mobdev_type_marke
LEFT JOIN tbl_user u
ON u.id = md.mobdev_user
AND CONCAT(u.name,' ',u.vorname) LIKE '%".$_POST['user']."%'
WHERE
CONCAT(m.marke_name,' ',COALESCE(mdt.mobdev_type_bezeichnung,''))
LIKE '%".$_POST['m.marke_name']."%'
AND md.mobdev_aktiv = '1'
ORDER BY
".$_GET['sort']." ".$_GET['sort2']."
Two asides -
As Rene M. says above, this code is an SQL Injection vulnerability. It might be safe due to its current application but I still wouldn't roll it out; the chances of someone taking this application or code fragment and later moving it online without doing a full audit is not insignificant, and you've then got a problem. Practice doing it right - don't leave SQL Injection vulnerabilities in code.
Please alias your table names! The query having every table name written out in full for each field reference makes it very bulky.

SQL Table Joins - What am I doing wrong?

I'm in a intro to database class, and one of my queries is seriously giving me trouble.
The assignment says to: Write a query to display the Passenger name, Seat No and Destination. Display this in one column title Travellers_info. This column should display data in the following format “ Mary Ann Jenkins is assigned to Seat 15 on the way to Bellmead”
This is the relationship view: http://prntscr.com/1jsoay
Can somebody please help me out, I'm not sure where I've gone wrong.
SELECT passenger.name + 'is assigned to Seat'
+ seat_info.seat_no + 'on the way to'
+ departure_info.destination AS Travellers_info
FROM passenger, seat_info, departure_info, seat_passenger, manages
WHERE passenger.Pass_id=seat_passenger.pass_id
AND seat_passenger.Seat_id=seat_info.Seat_id
AND seat_info.seat_id=manages.Seat_id
AND manages.Dept_id=departure_info.dept_id
You cant "add" text values using the "+" operator.
Without knowing which database you are using, the solution is probably either using CONCAT():
SELECT concat(passenger.name, 'is assigned to Seat', seat_info.seat_no,
'on the way to', departure_info.destination) AS Travellers_info
FROM passenger, seat_info, departure_info, seat_passenger, manages
WHERE passenger.Pass_id=seat_passenger.pass_id
AND seat_passenger.Seat_id=seat_info.Seat_id
AND seat_info.seat_id=manages.Seat_id
AND manages.Dept_id=departure_info.dept_id
or using the || operator:
SELECT passenger.name || 'is assigned to Seat'
|| seat_info.seat_no || 'on the way to'
|| departure_info.destination AS Travellers_info
FROM passenger, seat_info, departure_info, seat_passenger, manages
WHERE passenger.Pass_id=seat_passenger.pass_id
AND seat_passenger.Seat_id=seat_info.Seat_id
AND seat_info.seat_id=manages.Seat_id
AND manages.Dept_id=departure_info.dept_id
Have you tried double-checking all your tables (especially the joining tables like "manages" and "seat_passenger") to make sure you have valid data in them that would appropriately join up?
Also, make sure you have spaces in your text.
e.g.: 'is assigned to Seat' should be ' is assigned to Seat '
If you are getting no data it must be in your join criteria. Reduce your select to just a column from your first table and then join each table one at a time and see when it is that you stop getting data back
First off, you're going to want to put a space before is so that it won't look mushed together.
passenger.name + ' is assigned to seat'
Typically, you use subqueries and left outer joins for something of this sort. You do not just want to pull out all the data at once from all those tables. Let me see if I can explain this with some SQL. If you don't understand my example, go here: http://thenewboston.org/watch.php?cat=49&number=20 and watch 20-23 and you'll for sure understand it.
SELECT c.name + ' is assigned to Seat ' + c.seat_no + ' on the way to ' + departure_info.destination as Travellers_info
FROM departure_info
LEFT OUTER JOIN (SELECT b.Pass_id, b.name, b.seat_id, b.seat_no
FROM seat_no
LEFT OUTER JOIN (SELECT a.Pass_id, a.name, seat_passenger.seat_id
FROM seat_passenger
LEFT OUTER JOIN (SELECT passenger.name, passenger.Pass_id
from passenger
LEFT OUTER JOIN
ON passenger.Pass_id = seat_passenger.Pass_id) a seat_info
ON a.seat_id = seat_info.seat_id) b manages
ON b.seat_id = manages.seat_id) c departure_info
ON c.Dept_id = departure_info.Dept_id
I do not believe this will yield you the correct answer. But, it will get you working towards the right answer. I think I made a mistake after the third subquery. Remember that SQL evaluates things from the inside, then goes out. Just keep that in mind. Hope this helps.
try this in MSSQL or MSAccess.
for query optimization use ON (Join)
SELECT passenger.name + 'is assigned to Seat '
+ ltrim(rtrim(convert(char,seat_info.seat_no))) + ' on the way to'
+ departure_info.destination AS Travellers_info
FROM passenger p
join seat_passenger sp on sp.pass_id = p.Pass_id
join seat_info s on s.Seat_id = sp.Seat_id
join manages m on m.Seat_id = s.Seat_id
join departure_info d on d.dept_id = m.dept_id
concat in 2008R2 is not a valid function so you need to convert a number data to character.
while in 2012 it is available.

Joining on a many to many relationship with LINQ

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.

Slow SQL query when joining tables

This query is very very slow and i'm not sure where I'm going wrong to cause it to be so slow.
I'm guessing it's something to do with the flight_prices table
because if I remove that join it goes from 16 seconds to less than one.
SELECT * FROM OPENQUERY(mybook,
'SELECT wb.booking_ref
FROM web_bookings wb
LEFT JOIN prod_info pi ON wb.location = pi.location
LEFT JOIN flight_prices fp ON fp.dest_date = pi.dest_airport + '' '' + wb.sort_date
WHERE fp.dest_cheapest = ''Y''
AND wb.inc_flights = ''Y''
AND wb.customer = ''12345'' ')
Any ideas how I can speed up this join??
You're unlikely to get any indexing on flight_prices.dest_date to be used as you're not actually joining to another column which makes it hard for the optimiser.
If you can change the schema I'd make it so flight_prices.dest_date was split into two columns dest_airport and dest_Date as it appears to be currently a composite of airport and date. If you did that you could then join like this
fp.dest_date = wb.sort_date and fp.dest_airport = pi.dest_airport
Try EXPLAIN PLAN and see what your database comes back with.
If you see TABLE SCAN, you might need to add indexes.
That second JOIN looks rather odd to me. I'd wonder if that could be rewritten.
Your statement reformatted gives me this
SELECT wb.booking_ref
FROM web_bookings wb
LEFT JOIN prod_info pi ON wb.location = pi.location
LEFT JOIN flight_prices fp ON fp.dest_date = pi.dest_airport + ' ' + wb.sort_date
WHERE fp.dest_cheapest = 'Y'
AND wb.inc_flights = 'Y'
AND wb.customer = '12345'
I would make sure that following fields have indexes
dest_cheapest
dest_date
location
customer, inc_flights, booking_ref (covering index)