We have a employee table like
Employee ID
Name
EmployeeManager table like
employeeid
employeeManagerid
intyear
intperiod
So every manager is an employee, employeemanagerid is the forigen key from employee table and it is an employeeid from the employee table
An employee can have multiple managers in a year that is the reason for
intYear and intPeriod, intPeriod is the month so it will have value from 1-12
What i am trying to achieve is if a manager is selected in one period(months) and no manager is assigned for next three periods(months) then the same manager
will be assigned to that guy,
to give an example
employee table
----------------------------------------------------------------
employeeid name
1 a
2 b
3 c
4 d
5 e
-------------------------------------------------------------------
EmployeeManager table
----------------------------------------------------------------------
employeeid employeemanagerid intyear intperiod
-----------------------------------------------------------------------
1 5 2017 3
1 4 2017 4
2 4 2017 6
3 4 2017 6
------------------------------------------------------------------------
My query
select e.name,e.employeeid
from employee e
left join employeemanager em
on e.employeeid = em.employeeid
where
em.employeemanagerid = #managerid
and em.intyear = #intyear
and em.intperiod <= #intperiod
the values supplied as a parameter are
#managerid = 4
#intyear = 6
#intperiod = 2017
What i want as expected result is
------------------------------------------------------
name employeeid
a 1
b 2
c 3
------------------------------
Employee b,c is straight match but a has the manger set in period 4 which
is still continueing till period 6
what i should change in the query to get this result
the parameter values are sent from c#.
The problem is you are filtering out all records that are not for a specific manager, but you still expect those records to affect the results. You are also not doing anything to stop duplicates, if you had an employee go from manager 4 to 5 to 4 it would show twice. You need to get a query first that figures out who the correct manager is for each row for the period wanted, then do your main query from that first query. One way to do this is:
--This gets all manager records for the period (or before), with a rowno added
--sorted so that the most recent manager is always number 1
With emData as
(
Select employeeid, employeeManagerid, intyear, intperiod
, ROW_NUMBER() OVER(Partition by employeeid ORDER BY intyear DESC, intperiod DESC) as RowNo
from employeemanager
where intyear <= #intyear
and intperiod <=#intperiod
)
--This is your original query, changed to use the above as the source
select e.name,e.employeeid
from employee e inner join
emData em on e.employeeid = em.employeeid
where
em.employeemanagerid = #managerid
and em.RowNo = 1 --THIS MAKES SURE YOU ARE ONLY LOOKING AT THE MOST RECENT MANAGER
Related
I have a question regarding Linq in C#.
Let's say that I have 3 tables "Company", "Employee" and "Job".
Company
--------
Id - int (PK)
Name - string
Employee
--------
Id - int (PK)
CompanyId - int (FK on Company.Id)
Name - string
Job
--------
Id - int (PK)
CompanyId - int (FK on Company.Id)
EmployeeId - int (FK on Employee.Id)
Name - string
Something like that:
enter image description here
The important thing is that every work must be connected to a company but not necessarily to an employee. However, each employee must be connected to a company. For example we can have racord like that:
Company
--------
Id Name
1 'A'
2 'B'
3 'C'
Employee
--------
Id CompanyId Name
1 1 'A'
2 1 'B'
3 2 'C'
Job
--------
Id CompanyId EmployeeId Name
1 1 1 'clean'
2 1 2 'wash'
3 2 2 'buy'
4 3 NULL 'sell'
And now with linq I would like to get all jobs that are assigned to this employee and other employees from the same company.
So in this case it will should are jobs with id 1 and 2 becouse employee 1 is assigned to company 1 and job with id 2 also has assigned to this company. How could I achieve this using linq but something like this:
_context.Job.Where (x => x)
It is important to make only one query to the database.
Tkanks.
You can simplify the problem by thinking of it in two steps: find the company for a given employee, find all the jobs for that company:
var companyToFind = from e in Employee
where e.Id == empToFind
select e.CompanyId;
var jobsToFind = from j in Job
where companyToFind.Any(cid => cid == j.CompanyId)
select j;
In LINQ to SQL, EF Core 2.2 and EF Core 3.x the Any is translated to an EXISTS query in SQL.
Note since you know there should be only one answer to companyToFind, sending two queries to the database may be more efficient.
For LINQ to SQL or EF Core 3.x, you could also nest the first query and reduce to a single result:
var jobsToFind = from j in Job
where (from e in Employee
where e.Id == empToFind
select e.CompanyId).First() == j.CompanyId
select j;
I need help regarding a SQL query problem. I have a query where I am able to delete the duplicates but I also need to create records of the duplicated data being deleted into a EventLog in which I am clueless about it. Below is an example of my Student Table. From the table below, you can see only Alpha and Bravo are duplicated
id Name Age Group
-----------------------
1 Alpha 11 A
2 Bravo 12 A
3 Alpha 11 B
4 Bravo 12 B
5 Delta 11 B
As I am copying data from Group A to Group B, I need to find & delete the duplicated data in group B. Below is my query on deleting duplicates from Group B.
DELETE Student WHERE id
IN (SELECT tb.id
FROM Student AS ta
JOIN Student AS tb ON ta.name=tb.name AND ta.age=tb.age
WHERE ta.GroupName='A' AND tb.GroupName='B')
Here is an example of my eventlog and how I want the query that I execute to like.
id Name Age Group Status
------------------------------------------
1 Alpha 11 B Delete
2 Bravo 11 B Delete
Instead of inserting the entire Group B data into the eventlog, is there any query that can just insert the Duplicated Data into the event log?
If we are speaking about Microsoft sql, key is output clause, more details here https://msdn.microsoft.com/en-us/library/ms177564.aspx
declare #Student table
( id int, name nvarchar(20), age int,"groupname" char(1))
insert into #student values (1, 'Alpha' , 11, 'A' ),
(2, 'Bravo' , 12, 'A'),
(3 ,'Alpha' , 11 , 'B'),
(4 ,'Bravo' ,12 , 'B'),
(5 ,'Delta' ,11 , 'B')
declare #Event table
( id int, name nvarchar(20), age int,"groupname" char(1),"Status" nvarchar(20))
select * from #Student
DELETE #Student
output deleted.*, 'Deleted' into #Event
WHERE id
IN (SELECT tb.id
FROM #Student AS ta
JOIN #Student AS tb ON ta.name=tb.name AND ta.age=tb.age
WHERE ta.GroupName='A' AND tb.GroupName='B')
select * from #event
Run this before the Delete above. Not sure how you decide what one is the duplicate but you can use Row_Number to list them with the non duplicate at as 1 and and then insert everything with a row_Number > 1
; WITH cte AS
(
SELECT Name
,Age
,[Group]
,STATUS = 'Delete'
,RID = ROW_NUMBER ( ) OVER ( PARTITION BY Name,Age ORDER BY Name)
FROM Student AS ta
JOIN Student AS tb ON ta.name=tb.name AND ta.age=tb.age
)
INSERT INTO EventLog
SELECT Name,Age,[Group],'Delete'
FROM cte
WHERE RID > 1
you need to create basic trigger after delete in student table, this query will be executed after any deletion process in student table and will insert deleted record into log_table
create trigger deleted_records
on student_table
after delete
as
begin
insert into log_table
select d.id, d.Name, d.Age, d.Group, 'DELETED'
from DELETED d;
end
I am developing c# application.
I am using OLEDB connections.
I have following two tables>>
payment
AdmissionNumber | StudName |
1 John
2 Smith
paymentDetails
AdmissionNumber | RemainingFee | Date | Payment
1 5000 10/10/2012 3000
1 3000 10/11/2012 2000
2 4000 15/11/2012 3000
1 1000 10/12/2012 2000
In this I want to get the table result as following>>
AdmissionNumber | Name | Date |RemainingPayment|Payment|
1 John 10/12/2012 1000 2000
In this case Admission number and date is already provided in the form via textbox and datetimepicker.
In this case Admission number and date is already provided in the form
via textbox and datetimepicker.
So you want to search for a specific Admission number and a date. If so, then try this:
SELECT
p.AdmissionNumber,
p.Name,
pd.Date,
pd.RemaingFee AS RemainingPayment,
pd.Payment
FROM Payment p
INNER JOIN PaymentDetails pd ON p.AdmissionNumber = pd.AdmissionNumber
WHERE p.AdmissionNumber = #AdmissionNumberParamFromTxtBox
AND pd.Date = #DateParamFromTheotherTextBox;
This will give you the exact result. Matching between master and the last record of the details. You should have an Primary key column in the details.
Select *
From Payment
Left Outer Join
PaymentDetail
On PaymentDetail.Id = (
Select Top 1
A.Id
From PaymentDetail As A
Where A.AdmissionNumber = Payment.AdmissionNumber
Order By A.Date Desc
)
Cheers
SELECT
p.AdmissionNumber,
p.Name,
MAX(pd.Date) AS Date,
pd.RemaingFee AS RemainingPayment,
pd.Payment
FROM Payment p
INNER JOIN PaymentDetails pd ON p.AdmissionNumber = pd.AdmissionNumber
GROUP BY p.AdmissionNumber,pd.Payment,p.Name,pd.RemaingFee
I have several table related to multilingual Photo Galley like
AlbumCategories
AlbumName
Photos
PhotoDetails
Sample Table Structure of two table. I actually want a result set that will show me list of all records from Photos Table for particular AlbumID along with a custom column that will show TRUE or FALSE based on if particular PhotoID is present in the PhotoDetails Table
Table: Photos
PhotoID PhotoFile AlbumID
1 Photo1.jpg 7
2 Photo2.jpg 7
3 Photo3.jpg 5
4 Photo4.jpg 5
5 Photo5.jpg 7
6 Photo6.jpg 7
Table: PhotoDetails
PDID PhotoID PDTitle AlbumID LanguageID
11 1 Photo 1 7 1
22 2 Photo 2 7 1
33 3 Photo 3 5 1
44 4 Photo 4 5 1
DESIRED OUT PUT
PhotoID PDTitle AlbumID DetailPresent
1 Photo1 7 TRUE
2 Photo2 7 TRUE
5 Photo5 7 FALSE
6 Photo6 7 FALSE
I tried something several JOIN based queries but could not get the desired result
SELECT pd.PhotoTitle, p.PhotoTN,p.PhotoCreatedOn, pd.AlbumID, ISNULL(p.PhotoID,NULL) AS Missing FROM AlbumPhotos p
JOIN AlbumPhotoDetails pd
ON p.PhotoID = pd.PhotoID WHERE pd.AlbumID = 16
This query gives me the same result
SELECT pd.PhotoTitle, p.PhotoTN,p.PhotoCreatedOn, pd.AlbumID, ISNULL(p.PhotoID,NULL) AS Missing FROM AlbumPhotos p
JOIN AlbumPhotoDetails pd
ON p.PhotoID = pd.PhotoID WHERE pd.AlbumID = 16
OR p.PhotoID IN (SELECT PhotoID FROM AlbumPhotoDetails WHERE LanguageID = 1 AND AlbumID = 16)
Above query get me the result of matching based on PhotoID. I am lost how i can actually achieve the desired result as shown in the above sample 'DESIRED OUT PUT`
Use a left outer join.
The table examples that you have shown doesn't make any sense, as there is no field to connect them, and the PDTitle values that you want in the result doesn't exist in the example data.
Assuming that there is a PhotoId field in the PhotoDetails table (like in the AlbumPhotoDetails table that you use in the query that you show), and that the PhotoDetails table contains the titles that you want in the result, you can do like this:
select
p.PhotoId, d.PDTitle, p.AlbumId,
case when d.PhotoId is null then 'FALSE' else 'TRUE' end
from Photos p
left join PhotoDetails d on d.PhotoId = p.PhotoId
where p.AlbumId = 7
Note that the title will be null where there are no corresponding record in the PhotoDetails table.
once there are new data insert to my DB my rcount will increase by 1, what am i trying to do is to display latest inserted record to users, but i cant get my expected result
rCount in my datebase
1
2
3
4
5
output
5
4
3
1
2
expected output
5
4
3
2
1
"SELECT *, ROW_NUMBER() OVER (ORDER BY rCount DESC) AS 'RowNumber'
FROM [MovieListTable]"
Instead of using the row number you should introduce a numeric primary key (i.e. Id) and make it an Identity column. Now you can just select the row that has the maximum Id value:
select top 1 * from MovieListTable order by Id desc
Or to get all rows:
select * from MovieListTable order by Id desc