linq to entities - try this one! - sql

Im converting to linq to entities and I am finding problems attempting to convert the stored procs I have created as an overview of data.
How do I convert this sql statement to linq to entities:
I have a venue table with a child venuerooms table. With the last part I want to get the largest capacity for that venue across all rooms and roomtypes.
This is currently working in sql server 2005
Any help would be greately appreciated
ALTER proc [dbo].[sp_getVenueOverview]
(#venue varchar(100)) as
SELECT (Select accomrooms
from tblvenue
where venueid=(select venueid from tblvenue where urlfriendly = #venue))
as accomrooms,
(Select count(*)
from tblvenueroom
where venueid=(select venueid from tblvenue where urlfriendly = #venue))
as roomcount,
(Select Max(dbo.Greatest(theatrestyle,classroom,boardroom,ushape,banquet,cocktail))
from tblvenueroom
where venueid=(select venueid from tblvenue where urlfriendly = #venue))
as largest

you might want to refactor the query first, here is my try:
SELECT
v.accomrooms,r.roomcount,r.largest
FROM tblvenue v
LEFT OUTER JOIN (SELECT
v.venueid
,COUNT(*) AS roomcount
,Max(dbo.Greatest(r.theatrestyle,r.classroom,r.boardroom,r.ushape,r.banquet,r.cocktail) AS largest --dbo.Greatest() kills performance!
FROM tblvenue v
INNER JOIN tblvenueroom r ON v.venueid=r.venueid
WHERE v.urlfriendly = #venue
GROUP BY v.venueid
) dt ON v.venueid=dt.venueid
WHERE v.urlfriendly = #venue

Related

Query / design performance problem: How to get an Id via a 'link'-table in the most efficient way?

See this part from my ERD:
Part from the design
From a reader, I get a RFID which belongs to a wheel. How can I obtain the corresponding Id from the tblProduct-table. I know how to do it with a number of SELECT-statements, but is this the fastest way? I am asking this because I do not have a lot of experience generating speed-efficient QUERY Statements.
On the moment I did create a function to handle this:
CREATE FUNCTION [dbo].ufnGetProductIdFromRFID
(#StationRFID NVARCHAR(20))
RETURNS
INT
AS
BEGIN
DECLARE #ProductId INT = 0
DECLARE #WheelId INT = 0
SELECT #WheelId = [Id] FROM [dbo].[tblWheel] WHERE RFID = #StationRFID
SELECT #ProductId = [ProductId] FROM [dbo].[tblLinkWheelProduct] WHERE WheelId = #WheelId
RETURN #ProductId
END
GO
So i execute two query's.
My question: will a 'JOIN' or some other contruction lead to a more efficient (less executing time) solution? Since the two SELECT-statements are fairly simple and not time-consuming at all I think.....
Thanks already for thinking along with me!
In this way you can get whatever information from tblProduct table
select * from tblProduct p
where exists (
select 1 from tblLinkWheelProduct lwp
inner join tblWheel w
on w.Id = lwp.WheelId
where p.Id = lwp.ProductId and RFID = ?
)
if your intention is to only get productId then,
select productId from tblLinkWheelProduct lwp
where exists (
select 1 from tblWheel w
where w.id = lwp.WheelId
and w.RFID = ?
)
I would join tblWheel to tblLinkWhelProduct to tblProduct. You would get the data with one query. I think it is the best way:
select p.Id from tblWheel w
inner join tblLinkWheelProduct l on w.Id=t.WheelId
inner join tblProduct p on p.Id=l.ProductId

SQL Group By Clause and Empty Entries

I have a SQL Server 2005 query that I'm trying to assemble right now but I am having some difficulties.
I have a group by clause based on 5 columns: Project, Area, Name, User, Engineer.
Engineer is coming from another table and is a one to many relationship
WITH TempCTE
AS (
SELECT htce.HardwareProjectID AS ProjectId
,area.AreaId AS Area
,hs.NAME AS 'Status'
,COUNT(*) AS Amount
,MAX(htce.DateEdited) AS DateModified
,UserEditing AS LastModifiedName
,Engineer
,ROW_NUMBER() OVER (
PARTITION BY htce.HardwareProjectID
,area.AreaId
,hs.NAME
,htce.UserEditing ORDER BY htce.HardwareProjectID
,Engineer DESC
) AS row
FROM HardwareTestCase_Execution AS htce
INNER JOIN HardwareTestCase AS htc ON htce.HardwareTestCaseID = htc.HardwareTestCaseID
INNER JOIN HardwareTestGroup AS htg ON htc.HardwareTestGroupID = htg.HardwareTestGroupId
INNER JOIN Block AS b ON b.BlockId = htg.BlockId
INNER JOIN Area ON b.AreaId = Area.AreaId
INNER JOIN HardwareStatus AS hs ON htce.HardwareStatusID = hs.HardwareStatusId
INNER JOIN j_Project_Testcase AS jptc ON htce.HardwareProjectID = jptc.HardwareProjectId AND htce.HardwareTestCaseID = jptc.TestcaseId
WHERE (htce.DateEdited > #LastDateModified)
GROUP BY htce.HardwareProjectID
,area.AreaId
,hs.NAME
,htce.UserEditing
,jptc.Engineer
)
The gist of what I want is to be able to deal with empty Engineer columns. I don't want this column to have a blank second entry (where row=2).
What I want to do:
Group the items with "row" value of 1 & 2 together.
Select the Engineer that isn't empty.
Do not deselect engineers where there is not a matching row=2.
I've tried a series of joins to try and make things work. No luck so far.
Use j_Project_Testcase PIVOT( MAX(Engineer) for Row in ( [1], [2] ) then select ISNULL( [1],[2]) to select the Engineer value
I can give you a more robust example if you set up a SQL fiddle
Try reading this: PIVOT and UNPIVOT

Move data from SQL results to existing table

I'm a little bit stuck. I have a database table with the following columns:
Table Name: Data
*Value
*DateTime
*WeekNumber
*ItemId
*Name
I have created the following scripts from which I'd like to place the results into the above table.
SELECT D.*, M.Name
FROM
(SELECT SUM (Data) AS [Value],
(SELECT CONVERT(Date,DATEADD(week,-1,GETDATE()))) [DateTimeValue], DatePart (Week,TimestampUTC) [WeekNumber], MT.MeterId [MeterID]
FROM DataLog.dl
JOIN MeterTags mt ON dl.MeterTagId = mt.MeterTagId
GROUP BY DatePart (Week,TimestampUTC, dl.MeterTagId, MeterId)
AS D
INNER JOIN Meters m
ON D.MeterId = M.MeterId
ORDER BY MeterId DESC
I'm hoping to drop the results from the above query into the corresponding columns in the db table along with creating a new one for MeterID:
Value = Value
DateTime = DateTimeValue
WeekNumber = WeekNumber
MeterID = ***Need to create a new column*****
Name = Name
I hope this makes sense as I'm pretty inexperienced with SQL and a struggling to get the last pieces put together. Any help you can give would be greatly appreciated.
Thanks.
you can use the standard SQL INSERT syntax
INSERT INTO table2
SELECT * FROM table1;
what i don't understand is what do you mean by
MeterID = Need to create a new column**
for more info look
http://www.w3schools.com/sql/sql_insert_into_select.asp and
http://msdn.microsoft.com/en-us/library/ms188263(v=sql.105).aspx
Modify your table and add new column for MeterId.
Insert into [Data]
SELECT D.[Value], D.DateTimeValue,D.WeekNumber,MT.MeterId,M.Name
FROM
(SELECT SUM (Data) AS [Value],
(SELECT CONVERT(Date,DATEADD(week,-1,GETDATE()))) [DateTimeValue], DatePart (Week,TimestampUTC) [WeekNumber], MT.MeterId [MeterID]
FROM DataLog.dl
JOIN MeterTags mt ON dl.MeterTagId = mt.MeterTagId
GROUP BY DatePart (Week,TimestampUTC, dl.MeterTagId, MeterId)
AS D
INNER JOIN Meters m
ON D.MeterId = M.MeterId
ORDER BY MeterId DESC

PostgreSQL - how to query "result IN ALL OF"?

I am new to PostgreSQL and I have a problem with the following query:
WITH relevant_einsatz AS (
SELECT einsatz.fahrzeug,einsatz.mannschaft
FROM einsatz
INNER JOIN bergefahrzeug ON einsatz.fahrzeug = bergefahrzeug.id
),
relevant_mannschaften AS (
SELECT DISTINCT relevant_einsatz.mannschaft
FROM relevant_einsatz
WHERE relevant_einsatz.fahrzeug IN (SELECT id FROM bergefahrzeug)
)
SELECT mannschaft.id,mannschaft.rufname,person.id,person.nachname
FROM mannschaft,person,relevant_mannschaften WHERE mannschaft.leiter = person.id AND relevant_mannschaften.mannschaft=mannschaft.id;
This query is working basically - but in "relevant_mannschaften" I am currently selecting each mannschaft, which has been to an relevant_einsatz with at least 1 bergefahrzeug.
Instead of this, I want to select into "relevant_mannschaften" each mannschaft, which has been to an relevant_einsatz WITH EACH from bergefahrzeug.
Does anybody know how to formulate this change?
The information you provide is rather rudimentary. But tuning into my mentalist skills, going out on a limb, I would guess this untangled version of the query does the job much faster:
SELECT m.id, m.rufname, p.id, p.nachname
FROM person p
JOIN mannschaft m ON m.leiter = p.id
JOIN (
SELECT e.mannschaft
FROM einsatz e
JOIN bergefahrzeug b ON b.id = e.fahrzeug -- may be redundant
GROUP BY e.mannschaft
HAVING count(DISTINCT e.fahrzeug)
= (SELECT count(*) FROM bergefahrzeug)
) e ON e.mannschaft = m.id
Explain:
In the subquery e I count how many DISTINCT mountain-vehicles (bergfahrzeug) have been used by a team (mannschaft) in all their deployments (einsatz): count(DISTINCT e.fahrzeug)
If that number matches the count in table bergfahrzeug: (SELECT count(*) FROM bergefahrzeug) - the team qualifies according to your description.
The rest of the query just fetches details from matching rows in mannschaft and person.
You don't need this line at all, if there are no other vehicles in play than bergfahrzeuge:
JOIN bergefahrzeug b ON b.id = e.fahrzeug
Basically, this is a special application of relational division. A lot more on the topic under this related question:
How to filter SQL results in a has-many-through relation
Do not know how to explain it, but here is an example how I solved this problem, just in case somebody has the some question one day.
WITH dfz AS (
SELECT DISTINCT fahrzeug,mannschaft FROM einsatz WHERE einsatz.fahrzeug IN (SELECT id FROM bergefahrzeug)
), abc AS (
SELECT DISTINCT mannschaft FROM dfz
), einsatzmannschaften AS (
SELECT abc.mannschaft FROM abc WHERE (SELECT sum(dfz.fahrzeug) FROM dfz WHERE dfz.mannschaft = abc.mannschaft) = (SELECT sum(bergefahrzeug.id) FROM bergefahrzeug)
)
SELECT mannschaft.id,mannschaft.rufname,person.id,person.nachname
FROM mannschaft,person,einsatzmannschaften WHERE mannschaft.leiter = person.id AND einsatzmannschaften.mannschaft=mannschaft.id;

SQL Condition based dataset

I have a SQL Server database that I did not design.
The employees have degrees, licensures and credentials stored in a few different tables.
I have written the query to join all of this information together so I can see an over all result of what the data looks like. I have been asked to create a view for this data that returns only the highest degree they have obtained and the two highest certifications.
The problem is, as it is pre existing data, there is no hierarchy built into the data. All of the degrees and certifications are simply stored as a string associated with their employee number.
The first logical step was to create an adjacency list(I believe this is the correct term).
For example 'MD' is the highest degree you can obtain in our list. So I have given that the "ranking" of 1. The next lower degree is "ranked" as 2. and so forth.
I can join on the text field that contains these and return their associated rank.
The problem I am having is returning only the two highest based on this ranking.
If the employee has multiple degrees or certifications they are listed on a second or third row. From a logical standpoint, I need to group the employee ID, First name and Last name. Then some how concatenate the degrees, certifications and licensures based on the "ranking" I created for them. It is not a true hierarchy in the way that I am thinking about it because I only need to know the highest two and not necessarily the relationship between the results.
Another potential caveat is that the database must remain in SQL Server 2000 compatibility mode.
Any help that can be given would be much appreciated. Thank you.
select a.EduRank as 'Licensure Rank',
b.EduRank as 'Degree Rank',
EmpComp.EecEmpNo,
EmpPers.EepNameFirst,
EmpPers.EepNameLast,
RTRIM(EmpEduc.EfeLevel),
RTRIM(EmpLicns.ElcLicenseID),
a.EduType,
b.EduType
from empcomp
join EmpPers on empcomp.eeceeid = EmpPers.eepEEID
join EmpEduc on empcomp.Eeceeid = EmpEduc.EfeEEID
join EmpLicns on empcomp.eeceeid = EmpLicns.ElcEEID
join yvDegreeRanks a on a.EduCode = EmpLicns.ElcLicenseID
join yvDegreeRanks b on b.EduCode = EmpEduc.EfeLevel
I think I can see what your problem is - however I'm not sure. Joining the tables together has given you "double rows". The "quick-and-dirty" way to solve this query, would be to use Subqueries other than Joins. Doing so, you can select only the TOP 1 Degree, and TOP 2 certifications.
EDIT : Can you try this query ?
SELECT *
FROM employSELECT tblLicensures.EduRank as 'Licensure Rank',
tblDegrees.EduRank as 'Degree Rank',
EmpComp.EecEmpNo,
EmpPers.EepNameFirst,
EmpPers.EepNameLast,
RTRIM(tblDegrees.EfeLevel),
RTRIM(tblLicensures.ElcLicenseID),
tblLicensures.EduType,
tblDegrees.EduType
FROM EmpComp
LEFT OUTER JOIN EmpPers ON empcom.eeceeid = EmpPers.eepEEID
LEFT OUTER JOIN
-- Select TOP 2 Licensure Ranks
(
SELECT TOP 2 a.EduType, a.EduRank, EmpLicns.ElcEEID
FROM yvDegreeRanks a
INNER JOIN EmpLicns on a.EduCode = EmpLicns.ElcLicenseID
WHERE EmpLincs.ElcEEID = empcomp.eeceeid
ORDER BY a.EduRank ASC
) AS tblLicensures ON tblLicensures.ElcEEID = empcomp.Eeceeid
LEFT OUTER JOIN
-- SELECT TOP 1 Degree
(
SELECT TOP 1 b.EduType, b.EduRank, EmpEduc.EfeEEID, EmpEduc.EfeLevel
FROM yvDegreeRanks b
INNER JOIN EmpEduc on b.EduCode = EmpEduc.EfeLevel
WHERE EmpEduc.EfeEEID = empcomp.Eeceeid
ORDER BY b.EduRank ASC
) AS tblDegrees ON tblDegrees.EfeEEID = empcomp.Eeceeid
This is not the most elegant solution, but hopefully it will at least help you out in some way.
create table #dataset (
licensurerank [datatype],
degreerank [datatype],
employeeid [datatype],
firstname varchar,
lastname varchar,
efeLevel [datatype],
elclicenseid [datatype],
edutype1 [datatype],
edutype2 [datatype]
)
select distinct identity(int,1,1) [ID], EecEmpNo into #employeeList from EmpComp
declare
#count int,
#rows int,
#employeeNo int
select * from #employeeList
set #rows = ##rowcount
set #count = 1
while #count <= #ROWS
begin
select #employeeNo = EecEmpNo from #employeeList where id = #count
insert into #dataset
select top 2 a.EduRank as 'Licensure Rank',
b.EduRank as 'Degree Rank',
EmpComp.EecEmpNo,
EmpPers.EepNameFirst,
EmpPers.EepNameLast,
RTRIM(EmpEduc.EfeLevel),
RTRIM(EmpLicns.ElcLicenseID),
a.EduType,
b.EduType
from empcomp
join EmpPers on empcomp.eeceeid = EmpPers.eepEEID
join EmpEduc on empcomp.Eeceeid = EmpEduc.EfeEEID
join EmpLicns on empcomp.eeceeid = EmpLicns.ElcEEID
join yvDegreeRanks a on a.EduCode = EmpLicns.ElcLicenseID
join yvDegreeRanks b on b.EduCode = EmpEduc.EfeLevel
where EmpComp.EecEmpNo = #employeeNo
set #count = #count + 1
end
Have tables for employees, types of degrees (including a rank), types of certs (including a rank), and join tables employees_degrees and employees_certs. [It might be better to put degrees and certs in one table with a flag is_degree, if all their other fields are the same.] You can extract the existing string values and replace them with FK ids into the degree and cert tables.
The query itself is harder, because PARTITION BY is not available in SQL Server 2000 (according to Google). UW's answer has at least two problems: you need LEFT JOINs because not all employees have degrees and certs, and there is no ORDER BY to show what you want to take the best of. TOP 2 subqueries are particularly difficult to use in this context. So for that, I can't yet give an answer.