SQL Server Job Alerts, find matches from user saved searches - sql-server

I'm trying to create a script that checks user's 'saved searches' against live jobs.
The desired output would be a table/list of; JobID + JobSearchID.
To approach this I've created a temp table, #TempJobSavedSearches.
SELECT
JS.JobSearchID,
JS.JobSortByOptionID,
Radius,
JobTypeID,
JobSearchKeywordID,
TownCityLookupID,
CountryID,
WorkingHoursID,
SectorID,
SalaryFrom,
SalaryTo
INTO #TempJobSavedSearches
FROM UserJobSearches AS UJS
JOIN JobSearches AS JS ON UJS.JobSearchID = JS.JobSearchID
LEFT JOIN JobSearchJobTypes ON JS.JobSearchID = JobSearchJobTypes.JobSearchID
LEFT JOIN JobSearchStrings ON JS.JobSearchID = JobSearchStrings.JobSearchID
LEFT JOIN JobSearchTowns ON JS.JobSearchID = JobSearchTowns.JobSearchID
LEFT JOIN JobSearchWorkingHours ON JS.JobSearchID = JobSearchWorkingHours.JobSearchID
LEFT JOIN JobSearchCountries ON JS.JobSearchID = JobSearchCountries.JobSearchID
LEFT JOIN JobSearchSectors ON JS.JobSearchID = JobSearchSectors.JobSearchID
LEFT JOIN JobSearchSalaries ON JS.JobSearchID = JobSearchSalaries.JobSearchID
LEFT JOIN JobSortByOptions ON JS.JobSortByOptionID = JobSortByOptions.JobSortByOptionID
WHERE Alert = 1
This creates:
JobSearchID JobSortByOptionID Radius JobTypeID JobSearchKeywordID TownCityLookupID CountryID WorkingHoursID SectorID SalaryFrom SalaryTo
----------- ----------------- ----------- ----------- ------------------ ---------------- ----------- -------------- ----------- ----------- -----------
901 8 200 1 NULL 1 4 2 31 30001 40000
901 8 200 1 NULL 1 4 2 34 30001 40000
904 8 10 1 114 1 4 2 23 30001 40000
904 8 10 1 114 1 4 2 24 30001 40000
904 8 10 1 114 1 4 2 39 30001 40000
I then thought I could loop through each JobSearchID, and compare the respective data to my Jobs table.
Jobs:
JobID TownCityLookupID WorkingHoursID JobTypeID JobTitle JobDescription SalaryFrom SalaryTo
----- ---------------- -------------- --------- -------- -------------- ---------- --------
1 1 2 5 foo foo 10000 60000
2 1 2 1 foo foo 30000 60000
3 11 3 3 bar bar 70000 100000
Other link tables (some tables/columns excluded for brevity);
JobSectors
SectorID JobID
-------- -----
18 1
19 1
20 1
21 1
23 2
24 2
25 2
26 2
44 3
TownCities
TownCityLookupID CountryID
---------------- ---------
1 4
11 8
Here's my loop/attempt and comparing the results;
DECLARE #JobSearchID int = 0
DECLARE #CountryID int = 0
DECLARE #TownCityLookupID int = 0
DECLARE #WorkingHoursID int = 0
DECLARE #SalaryFrom int = 0
DECLARE #SalaryTo int = 0
WHILE(1 = 1)
BEGIN
SELECT #JobSearchID = MIN(JobSearchID)
FROM #TempJobSavedSearches WHERE JobSearchID > #JobSearchID
IF #JobSearchID IS NULL BREAK
-- store single vars
SELECT #CountryID = (SELECT TOP(1) CountryID FROM #TempJobSavedSearches WHERE JobSearchID = #JobSearchID)
SELECT #TownCityLookupID = (SELECT TOP(1) TownCityLookupID FROM #TempJobSavedSearches WHERE JobSearchID = #JobSearchID)
SELECT #WorkingHoursID = (SELECT TOP(1) WorkingHoursID FROM #TempJobSavedSearches WHERE JobSearchID = #JobSearchID)
SELECT #SalaryFrom = (SELECT TOP(1) SalaryFrom FROM #TempJobSavedSearches WHERE JobSearchID = #JobSearchID)
SELECT #SalaryTo = (SELECT TOP(1) SalaryTo FROM #TempJobSavedSearches WHERE JobSearchID = #JobSearchID)
-- should I be joining on jobs not on temp table?
SELECT #JobSearchID, JobID FROM #TempJobSavedSearches
INNER JOIN JobSectors ON #TempJobSavedSearches.SectorID = JobSectors.SectorID
INNER JOIN JobSortByOptions ON #TempJobSavedSearches.JobSortByOptionID = JobSortByOptions.JobSortByOptionID
INNER JOIN JobTypes ON #TempJobSavedSearches.JobTypeID = JobTypes.JobTypeID
INNER JOIN JobSearchKeywords ON #TempJobSavedSearches.JobSearchKeywordID = JobSearchKeywords.JobSearchKeywordID
WHERE
JobSearchID = #JobSearchID
AND CountryID = #CountryID
TownCityLookupID = #TownCityLookupID
AND WorkingHoursID = #WorkingHoursID
AND SalaryFrom < #SalaryTo
AND SalaryTo > #SalaryFrom
END
However its returning both IDs, where I expected only JobID 2 to be shown
JobSearchID JobID
----------- -----
901 1
901 2
901 1
901 2
901 1
901 2
901 1
901 2
901 1
901 2
901 1
901 2
901 1
901 2
901 1
901 2
Could anyone explain what I'm doing wrong. Or provide a link to some reading that could help?

Related

How to marge data from the table using sql server?

Hi i am create the one store procedure for the get data and send push notification.and i want to marge this data and get in to one raw. but how can do that i don't know. i need help please help me let me know how can do that.this is my query here below i have write :
This is query =>
SELECT N.NotificationId,
N.UserId,
N.ActionUserId,
(CASE WHEN N.NotificationTypeId = 1 THEN 1
WHEN N.NotificationTypeId = 7 THEN 3
ELSE
2
END) AS TypeId,
AU.ProfileImage,
AU.UserName,
N.IsRead,
(CASE WHEN N.NotificationTypeId = 1 THEN 1
WHEN N.NotificationTypeId = 7 THEN 3
ELSE
2
END) AS TypeId,
N.NotificationTypeId,
N.InsertDateTime
FROM Notifications N
INNER JOIN Users U ON N.UserId = U.UserId
INNER JOIN Users AU ON N.ActionUserId = AU.UserId
ORDER BY N.InsertDateTime DESC
This is my current o/p =>
NotificationId | UserId | ActionUserId | UserName | NotificationTypeId | InsertDateTime | ProfileImage
6 20 15 hbc 1 2017-06-22 17:14:16.803 20170416032403869.jpeg
5 20 16 tyu 1 2017-06-22 17:12:12.297 20170416031522534.jpeg
4 20 17 opl 1 2017-06-22 17:11:58.060 20170416031250102.jpeg
3 10 11 abc 1 2017-06-22 16:14:16.803 20170416032403867.jpeg
2 10 12 xyz 1 2017-06-22 16:14:12.297 20170416031522533.jpeg
1 10 13 rty 1 2017-06-22 16:13:58.060 20170416031250101.jpeg
This is my expected o/p =>
NotificationId | UserId | ActionUserId | UserName | NotificationTypeId | InsertDateTime | ProfileImage | NotificationText
6 20 15 hbc 1 2017-06-22 17:14:16.803 20170416032403869.jpeg hbc,tyu and 1 other users followed you
3 10 11 abc 1 2017-06-22 16:14:16.803 20170416032403867.jpeg abc,xyz and 1 other users followed you
i want to like this marge this data any one know how can do that please let me know.
You can do this with a derived table and some windowed functions. I have also added in a bit of logic to make sure the Notification Text has the correct English depending on the number of other users included:
-- Create test data
declare #Notifications table(NotificationID int, UserID int, ActionUserID int, NotificationTypeID int, InsertDateTime datetime);
declare #Users table(UserID int, UserName nvarchar(10), ProfileImage nvarchar(50))
insert into #Notifications values (6,20,15,1,'2017-06-22 17:14:16.803'),(5,20,16,1,'2017-06-22 17:12:12.297'),(4,20,17,1,'2017-06-22 17:11:58.060'),(3,10,11,1,'2017-06-22 16:14:16.803'),(2,10,12,1,'2017-06-22 16:14:12.297'),(1,10,13,1,'2017-06-22 16:13:58.060');
insert into #Users values (15,'hbc','20170416032403869.jpeg'),(16,'tyu','20170416031522534.jpeg'),(17,'opl','20170416031250102.jpeg'),(10,'aaa',''),(11,'abc','20170416032403867.jpeg'),(12,'xyz','20170416031522533.jpeg'),(13,'rty','20170416031250101.jpeg');
-- Specify UserID
declare #UserID int = 10;
-- Create Notification
with d as
(
select n.NotificationID
,n.UserID
,n.ActionUserID
,au.UserName
,n.NotificationTypeID
,n.InsertDateTime
,au.ProfileImage
,row_number() over (partition by n.UserID order by n.InsertDateTime desc) as rn
,count(*) over (partition by n.UserID) as c
from #Notifications n
join #Users au
on(n.ActionUserID = au.UserID)
)
select d.NotificationID
,d.UserID
,d.ActionUserID
,d.UserName
,d.NotificationTypeID
,d.InsertDateTime
,d.ProfileImage
,d.UserName
+ isnull(case when d2.c = 2
then ' and '
else ', '
end
+ d2.UserName
,'')
+ case when d2.c > 2
then ' and ' + cast(d2.c-2 as nvarchar(10)) + ' other users'
else ''
end
+ ' followed you' as NotificationText
from d
left join d as d2
on(d.UserID = d2.UserID
and d2.rn = 2
)
where d.rn = 1;
Output:
+----------------+--------+--------------+----------+--------------------+-------------------------+------------------------+-----------------------------------------+
| NotificationID | UserID | ActionUserID | UserName | NotificationTypeID | InsertDateTime | ProfileImage | NotificationText |
+----------------+--------+--------------+----------+--------------------+-------------------------+------------------------+-----------------------------------------+
| 3 | 10 | 11 | abc | 1 | 2017-06-22 16:14:16.803 | 20170416032403867.jpeg | abc, xyz and 1 other users followed you |
| 6 | 20 | 15 | hbc | 1 | 2017-06-22 17:14:16.803 | 20170416032403869.jpeg | hbc, tyu and 1 other users followed you |
+----------------+--------+--------------+----------+--------------------+-------------------------+------------------------+-----------------------------------------+
You can try this:
SELECT Q.NotificationId,
Q.UserId,
Q.ActionUserId,
(CASE WHEN Q.NotificationTypeId = 1 THEN 1
WHEN Q.NotificationTypeId = 7 THEN 3
ELSE
2
END) AS TypeId,
Q.ProfileImage,
Q.UserName,
Q.IsRead,
(CASE WHEN Q.NotificationTypeId = 1 THEN 1
WHEN Q.NotificationTypeId = 7 THEN 3
ELSE
2
END) AS TypeId2,
Q.NotificationTypeId,
Q.InsertDateTime
FROM ( SELECT N.UserId, N.ActionUserId, N.NotificationTypeId,
AU.ProfileImage, AU.UserName, N.IsRead, N.InsertDateTime, N.NotificationID
FROM Notifications N
INNER JOIN Users U ON N.UserId = U.UserId
INNER JOIN Users AU ON N.ActionUserId = AU.UserId
WHERE N.UserId = #UserId ) Q
INNER JOIN (SELECT MAX(NotificationID) AS MaxNotifID, UserID FROM
dbo.Notifications
WHERE UserID = #userID GROUP BY UserID ) R ON
Q.NotificationID = R.MaxNotifID AND Q.UserID = R.USerID
ORDER BY Q.InsertDateTime DESC

how to select all value from two table

tableA tableB
IdPrice price id tax IdPrice
---------------------- ------------------------------------
4 100 1 20 4
------------------------ ------------------ ------------------
5 150 2 10 6
------------------------ ------------------ ------------------
6 270
------------------------
result =
price id tax
---- --- ----
100 1 20
150 2 10
270 null null
my Query
SELECT price,id,tax
FROM tableB INNER JOIN
tableA ON tableA.IdPrice= tableB.IdPrice
but this result
price id tax
---- --- ----
100 1 20
150 2 10
SELECT
a.price as price, b.id as id, b.tax as tax
FROM
tableA a
LEFT OUTER JOIN
tableB b ON a.IdPrice = b.IdPrice
Use left outer join you can get all the records from tableA.

Need select 2 rows from Table2, which is joined with Table1. See description

For example i have a Table1:
ID Specified TIN Value DateCreated
----------------------------------
1 0 tin1 45 2014-12-30
2 1 tin2 34 2013-01-05
3 0 tin3 23 2015-02-20
4 3 tin4 47 2013-06-04
5 3 tin5 12 2012-04-02
And a Table2:
ID Table1ID RegistrationDate
----------------------------------
1 1 2015-10-12
2 2 2015-07-21
3 1 2015-11-26
4 1 2015-12-04
5 2 2015-09-18
I need select all columns from Table1 with first and last RegistrationDate column in Table2. The answer should be
ID Specified TIN Value DateCreated FirstRegDate LastRegDate
---------------------------------------------------------------
1 0 tin1 45 2014-12-30 2015-10-12 2015-12-04
2 1 tin2 34 2013-01-05 2015-07-21 2015-09-18
3 0 tin3 23 2015-02-20 NULL NULL
4 3 tin4 47 2013-06-04 NULL NULL
5 3 tin5 12 2012-04-02 NULL NULL
Hi one possible solution can be something similar to pseudo query below(if you can prepare the tables I will modify to reflect actual query)
SELECT table1.*, inlineTable2.firstRegDate, inlineTable2.lastRegDate
FROM Table1
LEFT JOIN
(
SELECT
Table1ID AS id,
MIN(registrationDate) as firstRegDate,
MAX(regsitrationDate) as lastRegDate
FROM table2
GROUP BY table1ID
) AS inlineTable2
ON table1.id = inlineTable2.id
You can group by all columns in table1, and look up the minumum and maximum registration date for the group:
select ID
, Specified
, ... other columns from table1 ...
, min(RegistrationDate)
, max(RegistrationDate)
from Table1 t1
left join
Table2 t2
on t1.ID = t2.Table1ID
group by
ID
, Specified
, ... other columns from table1 ...

SQL Server display first, second, and third values with same value

I am trying to create a query in SQL Server but having some difficulties. I will try to supply some sample data so it is easier. There are multiple tables I am trying to pull from:
Units:
UnitID
------
101
102
103
104
etc..
Jobs:
JobID
------
1
2
etc.
Job Units:
UnitID | JobID | DispatchDate
-----------------------------
102 | 12 | Dec 12 2015
104 | 14 | Dec 12 2015
102 | 18 | Dec 12 2015
108 | 18 | Dec 12 2015
102 | 11 | Dec 12 2015
104 | 10 | Dec 12 2015
What I would like for a desired outcome would reflect this data set:
UnitID | Job 1 | Job 2 | Job 3
------------------------------
102 | 12 | 18 | 11
103 | | |
104 | 14 | 10 |
105 | | |
106 | | |
107 | | |
108 | 18 | |
So basically, I want to display the job the Unit has been out to up to three jobs, but I still need to show the other units that haven't gone out, or only have gone out once or twice.
I currently am exporting this data set out to three separate listviews and using three separate stored procedures, but this isn't getting the job done and is a mess, so I won't even bother posting my code, but if needed I can.
Any help is greatly appreciated. Thanks!
Edit: As per request of /u/Pasty, here is the code I am working on:
select UnitID, case when (select COUNT(JobID)
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 12 2015') >= 1
then (select top 1 JobID
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 12 2015'
order by JobID asc )
else null
end as 'Job 1', case when (select COUNT(JobID)
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 12 2015') >= 2
then (select top 1 JobID
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 12 2015'
order by JobID desc )
else null
end as 'Job 2', case when (select COUNT(JobID)
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 12 2015') >= 3
then (select top 1 JobID
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 12 2015'
order by JobID asc )
else null
end as 'Job 3'
from Units U
order by UnitID asc
You need to use LEFT JOIN in order to achieve the desired result. If you have table A and B and want to display matches in B and all items from A, LEFT JOIN allow's you to do that. A good visual explanation of SQL JOINS can be found here - A Visual Explanation of SQL Joins.
How can you create the desired output in your case (I am assuming the tables are named Job, Unit ans Unit_has_Job):
Unit | UnitId
-----------
101
102
103
104
105
107
Job | JobId
--------------
1
2
3
4
5
Unit_has_JobId | UnitId | JobId
----------------------------------
101 | 1
101 | 3
101 | 4
102 | 4
105 | 3
select u.UnitId, ISNULL(j.JobId, 0) as [JobId] from unit as u
left join unit_has_job as uhj on u.UnitId = uhj.UnitId
left join job as j on uhj.JobId = j.JobId
The result is:
UnitId | JobId
101 | 1
101 | 3
101 | 4
102 | 4
103 | 0
104 | 0
105 | 3
107 | 0
I have created an example in SQL-Fiddle.
With the ISNULL function you mark the empty slots. The different JobId for every UnitId is equivalent to the columns in your desired output.
Using LINQ2SQL and the GroupBy method you can easily group the jobs per unit from the result and iterate over them:
var jobsPerUnit = result.GroupBy (r => r.UnitId);
foreach (var jobs in jobsPerUnit)
{
Console.WriteLine("Unit: " + jobs.Key);
foreach (var job in jobs)
{
if (job.JobId > 0)
{
Console.WriteLine("Job: " + job.JobId);
}
}
Console.WriteLine("=================");
}
The output:
Unit: 101
Job: 1
Job: 3
Job: 4
=================
Unit: 102
Job: 4
=================
Unit: 103
=================
Unit: 104
=================
Unit: 105
Job: 3
=================
Unit: 107
=================
Columns in SQL are the result of a selection/projection, which can't be created so easily dynamically. One possible solution is to use dynamic SQL in order to create a temp table, fill it and then select from this temp table, but the overhead is probably not worth it. You still need a cursor for this solution.
If you want to do everything on the SQL-side, then one possible solution would be to iterate with a cursor over the result and group by UnitId.
I was just playing around and this is what I came up with:
SQLFiddle
IF OBJECT_ID(N'dbo.UNITS', 'U') IS NOT NULL
DROP TABLE dbo.UNITS
GO
CREATE TABLE UNITS(ID INT IDENTITY(1, 1), UnitID INT, JobID INT, DispatchDate DATETIME)
GO
INSERT INTO UNITS
VALUES(102, 12, 'Dec 12 2015')
,(104, 14, 'Dec 12 2015')
,(102, 18, 'Dec 12 2015')
,(108, 18, 'Dec 12 2015')
,(102, 11, 'Dec 12 2015')
,(104, 10, 'Dec 12 2015')
,(103, NULL, NULL)
,(105, NULL, NULL)
,(106, NULL, NULL)
,(107, NULL, NULL)
GO
SELECT
UnitId
,Job_1 = JobIDs.value('/JobID[1]','INT')
,Job_2 = JobIDs.value('/JobID[2]','INT')
,Job_3 = JobIDs.value('/JobID[3]','INT')
FROM
(
SELECT
UnitID
,JobIDs = CONVERT(XML,'<JobID>'
+ REPLACE(Units.JobIDs, '|', '</JobID><JobID>')
+ '</JobID>')
FROM
(
SELECT DISTINCT
U.UnitId
,JobIDs = STUFF((
SELECT
'|' + CAST(UU.JobID AS NVARCHAR(25))
FROM
UNITS UU
WHERE
UU.UnitID = U.UnitID
ORDER BY
UU.ID, UU.JobID
FOR XML PATH (''), type).value('.', 'nvarchar(max)'), 1, 1, '')
FROM
UNITS U
GROUP BY
U.UnitID) Units) UJ
There is an easier way to get to the same result, where you don't need to run inner selects all the time. This yields a much simpler execution plan and faster execution if you put on the proper indexes.
Note that there is a LEFT JOIN in the inner query (LEFT JOIN JobUnits ju), that will produce an row for each row in Units, regardless if it has related JobUnit.
select UnitID,
SUM(CASE WHEN cnt=1 THEN JobID ELSE 0 END) AS Job1,
SUM(CASE WHEN cnt=2 THEN JobID ELSE 0 END) AS Job2,
SUM(CASE WHEN cnt=3 THEN JobID ELSE 0 END) AS Job3,
SUM(CASE WHEN cnt=4 THEN JobID ELSE 0 END) AS Job4,
SUM(CASE WHEN cnt=5 THEN JobID ELSE 0 END) AS Job5
FROM (
select ju.UnitID, ju.JobID, count(1) as cnt
FROM Units u
LEFT JOIN JobUnits ju on (u.UnitID = ju.UnitID)
LEFT JOIN JobUnits ju2 on (ju.UnitID = ju2.UnitID AND ju.UnitID <= ju2.UnitID)
)
GROUP BY UnitID
The only disadvantage of this SELECT that it will not preserve the order (12, 18, 11 in case of 102), instead it orders it ascending way (11, 12, 18) - I don't know if it is an advantage or disadvantage in your business case.
You can preserve the order if you compare the ROWNUMs, but that requires two more subselects, and I'm not sure if it worth or not.
I ended up solving this scenario with quite a mess of code, but it works and I'm tired, so I am just going to go with it.
select UnitID, case when (select COUNT(JobID)
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 4 2015') >= 1
then (select top 1 JobID
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 4 2015'
order by JobID asc )
else null
end as 'Job 1', case when (select COUNT(JobID)
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 4 2015') >= 1
then (select Customer
from Customers C
full
where CustomerID=())
else null
end as 'Customer 1',
case when (select COUNT(JobID)
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 4 2015') >= 2
then
(SELECT TOP 1 JobID
FROM
(
SELECT TOP 2 JobID
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 4 2015'
ORDER BY JobID desc
) sub
ORDER BY JobID asc)
else null
end as 'Job 2',
case when (select COUNT(JobID)
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 4 2015') >= 3
then
(SELECT TOP 1 JobID
FROM
(
SELECT TOP 3 JobID
from JobUnits
where UnitID=U.UnitID
and DispatchDate='Dec 4 2015'
ORDER BY JobID desc
) sub
ORDER BY JobID desc)
else null
end as 'Job 3'
from Units U
order by UnitID asc

Compare the values of column in SQL Server

Table_1 columns are:
======================
A B
======================
100 4
-----------
101 2
101 3
101 4
-----------
102 6
-----------
103 7
-----------
104 2
104 3
104 4
-----------
105 2
-----------
106 4
-----------
107 3
--------------------------------
Now I have input B parameter like '6' or '2,3,4'.
I want to get a result like this:
if input B parameter is '6', then output should be:
======================
A B
======================
102 6
If input B parameter is '2,3,4', then output should be:
======================
A B
======================
101 2
101 3
101 4
-----------
104 2
104 3
104 4
Just select the needed columns:
SELECT A, B
FROM Table_1
WHERE B IN (2,3,4)
EDIT:
If you need them only if all params are present
SELECT A, B
FROM Table_1
WHERE A IN (SELECT A FROM Table_1 WHERE B = 2) AND A IN (SELECT A FROM Table_1 WHERE B = 3) AND A IN (SELECT A FROM Table_1 WHERE B = 4)
You can try this one, for your specific requirement -
-- the last digit after = i.e. 3 should be replaced by number of inputs in check for our case it is 3 for (2,3,4)
SELECT A,B FROM Table_1 AS tbl1 WHERE B IN (2,3,4) AND (select COUNT(1) FROM Table_1 AS tbl2 WHERE B IN (2,3,4) AND tbl1.A = tbl2.A)
= 3
Please, have a look.
Thanks!
SELECT A
,B
FROM table_1
WHERE A IN (
SELECT A
FROM table_1
WHERE B = 2
)
AND A IN (
SELECT A
FROM table_1
WHERE B = 3
)

Resources