SQL Server Simple Query - sql-server

I have this tables on my database
Users,Courses,Semesters,SelectedCourses
Users : ID,Username,Password,EnterYear
Courses : ID,Name
Semesters : ID,Code
SelectedCourses : ID,SemesterID(FK to Semesters.ID),UserID(FK to Users.ID),CourseID(FK to Courses.ID)
Now, I have 2 or n CourseID and I want to get Users that selected this Courses together.
for example :
This is my SelectedCourses table :
Result must be :
I want to find Users that have CourseID(1) and CourseID(2) on their SelectedCourses list.
Only UserID = 1 have this two courses!

SELECT U.UserID
FROM Users U
WHERE NOT EXISTS ( SELECT C.CID
FROM Course C
WHERE C.CId in (1,2) AND
NOT EXISTS
(SELECT S.CID
FROM SelectedCourses S
WHERE S.CID = C.CID AND
S. UserID = U.UserID)
);
For each user we check that there is no course that is not taken by this user.
This works as long as the number of course is within the range of data type.

select
userId,count(distinct courseId)
from
selectedCourses
where
courseId in (1,2)
group by userId
having count(distinct courseId) > 1

Related

SQL : Im tring to work out, how to return last action per member

Id Mshp_Id Action
1 9029 Register
2 9029 Create CV
3 8476 Register
4 8476 Create CV
5 8476 JOB SEARCH
I want to return the two membership ID's and their latest action.
so what would be left is ID 2 AND 5 ONLY.
If you are using SQL Server 2012+, you can use LAST_VALUE
SELECT ID,
,mshp_id
,action
FROM (
SELECT *,LAST_VALUE(id) OVER (PARTITION BY mshp_id
ORDER BY ID
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
) last_val
FROM YOUR_TABLE
) a
WHERE id = last_val
ORDER BY ID
Check Demo here
Output
Last action per member can be fetched through the following ways
Solution 1:
select Id, Mshp_Id, Action from (
select *, row_number() over (partition by Mshp_Id order by id desc) r from user_action
) a
where a.r = 1
order by id
Solution 2
select u.* from user_action u
join (select Mshp_Id, max(id) id from user_action
group by Mshp_Id ) a
on a.Mshp_Id = u.Mshp_Id and a.id = u.id
order by u.id
Good luck with your work !

Select count with Except clause takes too long

I'm executing two queries. One that return the number of records and one that fetch the results. But the query where i only want the total of records , it takes the same time than the query that fetch the results. Why ? Here's my SQL. i'm using SQL 2014 :
(SELECT count(*) as id
FROM (
SELECT DISTINCT title, version
FROM book AS b
WHERE b.title IS NOT NULL AND NOT EXISTS (SELECT * FROM user AS u WHERE u.column1 = b.column1)
group by title, version
EXCEPT
SELECT DISTINCT title, version
FROM book AS b
WHERE b.title IS NOT NULL AND EXISTS (SELECT * FROM user AS u WHERE u.column2 = b.column1)
group by title, version
) c )
Try this:
(SELECT count(*) as id
FROM (
SELECT DISTINCT title, version
FROM book b left join user u on b.column1=u.column1
WHERE b.title IS NOT NULL and u.column1 is null
EXCEPT
SELECT DISTINCT title, version
FROM book b join user u on b.column1=u.column2
WHERE b.title IS NOT NULL
) c )
Hmmm . . . for performance, try removing the group by and select distinct (except does this anyway):
SELECT count(*) as id
FROM (SELECT title, version
FROM book b
WHERE b.title IS NOT NULL AND NOT EXISTS (SELECT 1 FROM user u WHERE u.column1 = b.column1)
EXCEPT
SELECT title, version
FROM book b
WHERE b.title IS NOT NULL AND EXISTS (SELECT 1 FROM user u WHERE u.column2 = b.column1)
) c;
Next: Be sure you have an index on user(column2) and user(column1).
With more information about the data, it might be possible to make further suggestions.

SQL 2005 returning unique results with subquery

I have a database Table a (EMAILS) where EmailID is the Primary Key
EmailID Email_To Email_From Email_Subject Email_Registered Email_Read
If a user creates an email it is registered in this table.
For example, the user "Dave" who has id 3 sends an email to "John" who has id 4
So this would give
EmailID Email_To Email_From Email_Subject Email_Registered Email_Read
10 4 3 TEST 2/23/2016 11:00 False
To return results I do this select (joining the user profile database)
SELECT PROFILE_1.SellerID, PROFILE_1.Seller_UserName, EMAILS.EmailID, EMAILS.Email_From, EMAILS.Email_To, EMAILS.Email_Subject,
EMAILS.Email_Registered, EMAILS.Email_Read,
(SELECT Seller_UserName AS Epr2
FROM PROFILE
WHERE (SellerID = EMAILS.Email_To)) AS Expr2
FROM PROFILE AS PROFILE_1 LEFT OUTER JOIN
EMAILS ON EMAILS.Email_From = PROFILE_1.SellerID
WHERE (EMAILS.Email_From IS NOT NULL) AND (PROFILE_1.Seller_UserName = 'Dave')
ORDER BY EMAILS.Email_Registered DESC
So John Replies to Dave's email and it goes into the EMAILS_THREAD table and is registered as
EmailThreadID EmailID Email_To Email_From Email_Registered Email_Read
1 10 3 4 2/23/2016 11:05 False
What I am trying to do is a select that
SELECTS from EMAILS where Email_From is from Dave and return in the results the top 1 result from EMAIL_THREADS that is sent to Dave (based on Email_Registered) with the same EmailID as the EMAILS.EmailID if there is a entry in EMAIL_THREADS.
So in other words return the result of the EMAIL table and latest corresponding result in the EMAIL_THREADS table if there is one.
I hope this makes sense.
I've tried a ton of combinations and I can't figure this out.
At first I thought it was a subquery or a join or a group by...but i can't seem to nail the select and how it is structured.
Looking for some help.
Here is my last attempt
SELECT PROFILE_1.SellerID, PROFILE_1.Seller_UserName, EMAILS.EmailID, EMAILS.Email_From, EMAILS.Email_To, EMAILS.Email_Subject,
EMAILS.Email_Registered, EMAILS.Email_Read,
(SELECT Seller_UserName AS Epr2
FROM PROFILE
WHERE (SellerID = EMAILS.Email_To)) AS Expr2
FROM PROFILE AS PROFILE_1 LEFT OUTER JOIN
EMAILS ON EMAILS.Email_From = PROFILE_1.SellerID CROSS JOIN
(SELECT TOP (1) EMAILS_THREAD.Email_From, EMAILS_THREAD.Email_To, EMAILS_THREAD.Email_Registered, EMAILS_THREAD.Email_Read
FROM EMAILS_THREAD LEFT OUTER JOIN
EMAILS AS EMAILS_1 ON EMAILS_THREAD.EmailID = EMAILS_1.EmailID) AS derivedtbl_1
WHERE (EMAILS.Email_From IS NOT NULL) AND (PROFILE_1.Seller_UserName = 'Dave')
ORDER BY EMAILS.Email_Registered DESC
But it's not returning anything from EMAILS_THREADS at all.
SELECTS from EMAILS where Email_From is from Dave and return in the results the top 1 result from EMAIL_THREADS that is sent to Dave (based on Email_Registered) with the same EmailID as the EMAILS.EmailID if there is a entry in EMAIL_THREADS.Hope this helps
with cte
as
(select
* from emails
where email_from=3
)
select * from cte mt --only for dave
outer apply
(
select top 1* from
emial_threads st where mt.mail_from=st.mail_to ---send to dave
and mt.emailid=st.emailid) b
Haven't been able to find a solution to this so I am paying a SQL professional to resolve this for me. Thanks for the input from Tab and The Gameiswar. Much appreciated.

Postgres Proper usage of Group by in a Inner Join Statement

EDIT I updated my question with a SQL Fiddle Sample http://sqlfiddle.com/#!15/8d88b/1
I'm currently making a report from a database records but I don't know how my query should look like, first of all I have 2 tables. Application Forms, and a table for Login Hours of each user
forms
->id
->agent_id
->SomeInfo
->created_at
loginhours
->id
->user_id
->loginhours (decimal)
->created_at
And I have report with the following columns
UserID, TotalLoginHours, TotalApplication, Application Per Hour (aph), Revenue Per Hour (rph)
So right now I have this query
SELECT a.agent_id, SUM(b.loginhours) as TotalLoginHours, COUNT(a.id) as TotalApplication, SUM(b.loginhours) / COUNT(a.id) as ApplicationPerHour, (SUM(b.loginhours) / COUNT(a.id)) * 1.75 as RPH
FROM forms a
INNER JOIN loginhours b ON a.agent_id = b.user_id WHERE a.created_at = '2015-07-17'
GROUP BY a.agent_id
Note that user_id and agent_id is the same.
I want to get the result based on the date selected, example 2015-07-17 I got results but my problem is the loginhours is being SUM based on the number of application for each user. So for example the user1 has 2 records on forms table and his loginhours from 2015-07-17 is 2 then in my result the loginhours becomes 4 which is wrong, I think it is on my GROUP BY statement. Can you help me how to properly query this?
Thanks
I don't know if this is a good practice but somehow I figured it out with
SELECT a.agent_id
,(SELECT SUM(loginhours)
FROM loginhours
WHERE user_id = a.agent_id
AND created_at = '2015-07-17'
GROUP BY created_at) as TotalLoginHours
,COUNT(a.id) as TotalApplication
,(SELECT SUM(loginhours)
FROM loginhours
WHERE user_id = a.agent_id
AND created_at = '2015-07-17'
GROUP BY created_at) / COUNT(a.id) as ApplicationPerHour
,((SELECT SUM(loginhours)
FROM loginhours
WHERE user_id = a.agent_id
AND created_at = '2015-07-17'
GROUP BY created_at) / COUNT(a.id)) * 1.75 as RPH
FROM forms a
INNER JOIN loginhours b
ON a.agent_id = b.user_id
WHERE a.created_at = '2015-07-17'
GROUP BY a.agent_id;
SELECT user_id, loginhours, applications,
loginhours/applications as applications_per_hour,
loginhours/applications * 1.75 as rph
FROM
(
SELECT user_id, SUM(loginhours) as loginhours
FROM loginhours
WHERE created_at = '2015-07-17'
GROUP BY user_id
)hours
JOIN
(
SELECT agent_id, COUNT(DISTINCT id) as applications
FROM forms
WHERE created_at = '2015-07-17'
GROUP BY agent_id
)applications
ON hours.user_id = applications.agent_id

Select 1 of 2 similar records where does not

So I have a table called 'Requests' which stores requests for holidays. I want to try extract certain records from the table (joined with others) with the parameter of the clocknumber. But, if there are two records with the same HolidayID and the last (top 1 desc) is of a certain value - we dont include that in the select!
Request Table [shortened down version of it];
http://i.stack.imgur.com/YY1Gk.png
The stored procedure im using is passed a parameter for the username and joins three other tables,
a 'Holidays' table (Stores information on the holiday from, to etc)
a 'Users' table (contains usernames etc)
a 'RequestType' table (contains the types of requests)
From the image of the table, If you imagine all of those requests belong to the same user, I would want to extract only the records with a requesttype of 1. (the requesttype 1 is holiday request and 2 is holiday cancel). But, if there is a second record with the same holidayID and a requesttype of 2, it does not include that.
So running the query, I would want to only get records with the ID 1 and 2, because the last 2 have the same Holiday ID, and the last of the 2 is with a requesttype to cancel the holiday.
Here is my attempted query;
SELECT Holidays.ID, EmployeeClockNumber, Employees.Name AS EmployeeName, HolidayStart, HolidayEnd, HalfDay, AMPM
FROM Holidays
INNER JOIN Employees ON Employees.ClockNumber = Holidays.EmployeeClockNumber
INNER JOIN Requests ON Requests.HolidayID = Holidays.ID
WHERE EmployeeClockNumber = #ClockNo
AND Requests.Accepted = 1
AND RequestTypeID = (SELECT TOP 1 Requests.ID
FROM Requests
INNER JOIN Holidays ON Holidays.ID = Requests.HolidayID
WHERE Requests.RequestTypeID = (SELECT ID FROM RequestType WHERE RequestType = 'Holiday Request')
AND Holidays.EmployeeClockNumber = #ClockNo
ORDER BY Requests.ID DESC)
ORDER BY ID DESC
Could someone point me in the right direction? Thank you
edit: ive got it working myself!
SELECT Holidays.ID, Holidays.EmployeeClockNumber, Employees.Name AS EmployeeName, Holidays.HolidayStart, Holidays.HolidayEnd, Holidays.HalfDay, Holidays.AMPM
FROM Requests
INNER JOIN Holidays ON Holidays.ID = Requests.HolidayID
INNER JOIN Employees ON Employees.ClockNumber = Holidays.EmployeeClockNumber
WHERE Holidays.EmployeeClockNumber = #ClockNo
AND Requests.Accepted = 1
AND Requests.HolidayID NOT IN (SELECT TOP 1 HolidayID
FROM Requests AS R1
WHERE R1.RequestTypeID <> (SELECT ID FROM RequestType WHERE RequestType = 'Holiday Request')
AND R1.HolidayID = Requests.HolidayID
ORDER BY R1.ID DESC)
SELECT * FROM TAB WHERE requestTypeID = 1
AND holidayID not in (SELECT HolidayID from TAB WHERE requestTypeID = 2)
I would use a partition on the select and then filter on that.
So something like
DECLARE #mtable TABLE (
ID INT
,RequestTypeId INT
,HolidayId INT
,Accepted NVARCHAR(50)
)
INSERT #mtable VALUES (1,1,1,'True')
INSERT #mtable VALUES (2,1,2,'True')
INSERT #mtable VALUES (3,1,3,'True')
INSERT #mtable VALUES (4,2,3,'True')
SELECT * FROM (
SELECT MAX(RequestTypeId) OVER (PARTITION BY HolidayID) AS MaxType
,Id
FROM #mtable
) q
WHERE q.MaxType <> 2

Resources