TSQL Insert missing dates and increments - sql-server

In SQL Server 2008 R2, I have a table (StatDays) that contains a count of days (DaysInStatus) that an order was in a particular status. There is an entry for each day the order remained in that status, except for Sundays when there was no process to write to this table. In that case, the order would appear again on Monday, with DaysInStatus advanced two days.
My problem is how to populate the missing Sunday values. (I am assuming that if an order has a Saturday entry but no Monday entry, that Saturday is the last desired data point.)
Example:
OrderID StatDate DaysInStatus
A11111 6/1/2012 20
A11111 6/2/2012 21
A11111 6/4/2012 23
A11111 6/5/2012 24
A11111 6/6/2012 25
A11111 6/7/2012 26
A11111 6/8/2012 27
A11111 6/9/2012 28
A11111 6/11/2012 30
Here I would want to insert (or select) into another table all of these values, plus the missing dates 6/3 and 6/10 - where DaysInStatus is advanced to 22 and 29, respectively - and the OrderID.
Also, an OrderID will NOT always appear in this table at DaysInStatus = 1. In can appear at almost any value, and drop out at almost any value.
I have tried generating a dates table, then doing left outer join to StatDays on statDate and StatDate+1, StatDate-1. This works for small recordsets but the actual table has over 100 million records, so this would not work for me.
Thanks in advance for any suggestions!

This is your statement
INSERT Status
SELECT s1.OrderID
,DATEADD(day,1,s1.StatDate)
,s1.DaysInStatus+1
FROM Status s1
INNER JOIN
Status s2 ON DATEADD(day,2,s1.StatDate)=s2.StatDate
AND
s1.DaysInStatus+2=s2.DaysInStatus
LEFT JOIN
Status s3 ON DATEADD(day,1,s1.StatDate)=s3.StatDate
AND
s1.DaysInStatus+1=s3.DaysInStatus
WHERE DATENAME(dw,s1.StatDate)='Saturday'
AND
s3.OrderID IS NULL
You can see an SQLFiddle here

Try this. It will help with any missing days.
create table StatDays(OrderID varchar(20),StatDate datetime,
DaysInStatus int)
insert into statdays values('A11111', '6/1/2012', 20)
insert into statdays values('A11111', '6/2/2012', 21)
insert into statdays values('A11111', '6/4/2012', 23)
insert into statdays values('A11111', '6/5/2012', 24)
insert into statdays values('A11111', '6/6/2012', 25)
insert into statdays values('A11111', '6/7/2012', 26)
insert into statdays values('A11111', '6/8/2012', 27)
insert into statdays values('A11111', '6/9/2012', 28)
insert into statdays values('A11111', '6/11/2012', 30)
insert into statdays values('A11112', '6/1/2012', 20)
insert into statdays values('A11112', '6/2/2012', 21)
insert into statdays values('A11112', '6/4/2012', 23)
insert into statdays values('A11113', '6/5/2012', 24)
insert into statdays values('A11113', '6/6/2012', 25)
insert into statdays values('A11113', '6/7/2012', 26)
insert into statdays values('A11113', '6/8/2012', 27)
insert into statdays values('A11113', '6/9/2012', 28)
insert into statdays values('A11113', '6/13/2012', 32)
with
demo_cte as
(select orderid, min(statdate) Min_Date,max(statdate) Max_Date,
min(DaysInStatus) Min_Day from StatDays group by orderid
union all
select orderid,DateAdd(day,1,Min_Date), Max_date,Min_day+1 from demo_cte
where DateAdd(day,1,Min_Date)<=Max_date
)
select OrderId,Min_Date Stat_days,Min_Day from demo_cte
order by orderid
SQL Fiddle

Related

Time Duration for staff on a night shift with onguard system accesscontrol database

I am using the Lenel Onguard with SQL server dBase to make the time attendance system for our employees.
I summarize each day's transaction to make their first entry and last exit for each day and get the datediff. to get the time duration. But the problem is with night shift employees, it is showing the time out which happened in the morning of the same day where actual exit is on the next day. so the datediff. returning with wrong value. Any solutions are most welcomed!
This code gives me the wrong value for night shift.can anyone help me out to modify the code to fit staff on day shift and those on night shift in which their exit time is on next day
SELECT DISTINCT
BADGE.ID,
UPPER(ISNULL(dbo.EMP.FIRSTNAME, ' ') + ' ' + ISNULL(dbo.EMP.LASTNAME, ' ') + ' ' + ISNULL(dbo.EMP.MIDNAME, ' '))AS NAMES,
A.*,
B.TIMEOUT,
datediff(hour,a.[TIMEIN],b.TIMEOUT) HoursWorked
FROM (
SELECT empid,convert(date,event_time_utc)[Date],ltrim(right(convert(varchar(25), DATEADD(HOUR,3,CAST(min(event_time_utc)AS TIME)), 100), 7)) TIMEIN
FROM events INNER JOIN READER ON EVENTS.DEVID=READER.READERID INNER JOIN EVENT ON EVENTS.EVENTTYPE=EVENT.EVTYPEID AND EVENTS.EVENTID=EVENT.EVID
WHERE READERID=19 AND PANELID=16 AND EVDESCR='Access Granted'
GROUP BY empid,convert(date,event_time_utc)
) A
JOIN
(
SELECT empid,convert(date,event_time_utc)[Date],ltrim(right(convert(varchar(25), DATEADD(HOUR,3,CAST(MAX(event_time_utc)AS TIME)), 100), 7)) TIMEOUT
FROM events INNER JOIN READER ON EVENTS.DEVID=READER.READERID INNER JOIN EVENT ON EVENTS.EVENTTYPE=EVENT.EVTYPEID AND EVENTS.EVENTID=EVENT.EVID
WHERE READERID=20 AND PANELID=16 AND EVDESCR='Access Granted'
GROUP BY empid,convert(date,event_time_utc)
) B on A.empid=b.empid and a.[Date]=b.[Date]
JOIN Emp on emp.id=A.EmpID
JOIN BADGE ON BADGE.EMPID=A.EMPID
ORDER BY DATE
Results
EmpID TIMEIN Timeout
1 2014-08-21 21:38:06.000 2014-08-22 06:00:10.000
2 2014-08-22 22:30:00.000 2014-08-23 06:00:10.000
In summary you have Event/s table, that have EmpId, the datetime of each scan, and there is no info about TimeOut or TimeIn, and you want to find that, well from the information you provided its a bit hard, Im sure you have more data that will help make this simpler, like the shift hours, any limitations, is over hours accepted and more boundary information.
Lets say you dont, so we will need to put some assumptions, for example, as the employees work in shifts, I will assume that the shift is 8-10 hours, and if I see a gab in scanning more than 14 hours that the employee went home, I will not care if he is a night shift employee or a day shift, if there is a gab between two sequentialscans more than 14 hours that mean he went home, or in other words that is a TimeOut, and then next entry is a TimeIn.
You did not provide any table structure or data, so I will ignore your query and focus on the problem you want to solve, so I will assume I have only one Events Table that have all the data, you can adapt this to your query if this helps you.
I will create a memory table here and fill it with EmpId 1, that is a on the day shift and EmpId 2 that is on the night shift, I will assume some data and do some calculations.
Declare #Events TABLE(
EmpId int,
event_time_utc datetime
)
insert into #Events values
(1, '2014-08-21 07:38:06.000'),--first day for emp1
(1, '2014-08-21 08:39:06.000'),
(1, '2014-08-21 14:44:06.000'),
(1, '2014-08-21 15:38:06.000'),
(1, '2014-08-21 16:01:06.000'),
(1, '2014-08-22 07:40:06.000'),--second day for emp1
(1, '2014-08-22 08:50:06.000'),
(1, '2014-08-22 14:30:06.000'),
(1, '2014-08-22 15:30:06.000'),
(1, '2014-08-22 16:05:06.000'),
(1, '2014-08-23 07:38:06.000'),--3rd day for emp1
(1, '2014-08-23 08:39:06.000'),
(1, '2014-08-23 14:44:06.000'),
(1, '2014-08-23 15:38:06.000'),
(1, '2014-08-23 16:01:06.000'),
(1, '2014-08-24 07:40:06.000'),--4th day for emp1
(1, '2014-08-24 08:50:06.000'),
(1, '2014-08-24 14:30:06.000'),
(1, '2014-08-24 15:30:06.000'),
(1, '2014-08-24 16:05:06.000'),
(2, '2014-08-21 21:38:06.000'),--first day for emp2 -- night shift
(2, '2014-08-21 23:38:06.000'),
(2, '2014-08-22 01:38:06.000'),
(2, '2014-08-22 04:05:06.000'),
(2, '2014-08-22 21:38:06.000'),--first day for emp2 -- night shift
(2, '2014-08-22 23:38:06.000'),
(2, '2014-08-23 01:38:06.000'),
(2, '2014-08-23 04:05:06.000'),
(2, '2014-08-23 21:38:06.000'),--3rd day for emp2 -- night shift
(2, '2014-08-23 23:38:06.000'),
(2, '2014-08-24 01:38:06.000'),
(2, '2014-08-24 04:05:06.000'),
(2, '2014-08-24 21:38:06.000'),--4th day for emp2 -- night shift
(2, '2014-08-24 23:38:06.000'),
(2, '2014-08-25 01:38:06.000'),
(2, '2014-08-25 04:05:06.000')
Now I will use the below CTEs to figure out the TimeIn and TimeOut and calculate the hours.
;with cte as (
--get the next entry, and set a row number based on EmpID and time
select *
,LEAD(event_time_utc,1) over (partition by EmpId order by event_time_utc) nextEntry
,ROW_NUMBER() over (partition by EmpId order by event_time_utc) seq
from #Events
),cte2 as (
--count the hours between this entry and the one after
select *,datediff(hour,event_time_utc,nextEntry) [hours] from cte
),cte3 as (
--if gab more then 14 or if its null, set it as time in
select *
,case when seq=1 then event_time_utc
when [hours]>14 then nextEntry
else null end [TimeIn]
from cte2
),cte4 as (
--find the seq for the Timeout
select *,
Isnull(
lead(seq) over (partition by EmpId order by event_time_utc)
,(select top(1) cte.seq from cte where cte.EmpId=cte3.EmpId order by event_time_utc desc)) [TimeOutSeq]
from cte3 where TimeIn is not null
),cte5 as (
--convert the seq to timeout by joining to the same table using the TimeOutSeq to help
select cte4.*,cte3.event_time_utc [TimeOut] from cte4
left outer join cte3 on cte3.seq=cte4.TimeOutSeq and cte3.EmpId=cte4.EmpId
)
--select * from cte3
--finally show the needed fileds only, and the hours for each employee
select EmpId,seq,TimeIn,[TimeOut],datediff(Hour,TimeIn,[TimeOut]) [hours] from cte5 order by EmpId, TimeIn
The result for my set of data is as below:-
EmpId Seq TimeIn TimeOut hours
1 1 2014-08-21 07:38:06.000 2014-08-21 16:01:06.000 9
1 5 2014-08-22 07:40:06.000 2014-08-22 16:05:06.000 9
1 10 2014-08-23 07:38:06.000 2014-08-23 16:01:06.000 9
1 15 2014-08-24 07:40:06.000 2014-08-24 16:05:06.000 9
2 1 2014-08-21 21:38:06.000 2014-08-22 04:05:06.000 7
2 4 2014-08-22 21:38:06.000 2014-08-23 04:05:06.000 7
2 8 2014-08-23 21:38:06.000 2014-08-24 04:05:06.000 7
2 12 2014-08-24 21:38:06.000 2014-08-25 04:05:06.000 7

How to re write while loop using cte

I have two tables, one with Events, the other with episodes.
An Episode has a start date and end date, the event has a single date.
Both Episodes and Events have one of six Types.
Currently I'm using some fuzzy logic to run an update script on the Events table to set it's ID field to the matching Episode. It does this by checking for the Event date between the Episode start and end, both having the same Type, as well as some other links like same User etc.
Since the Events can sit outside of the Episode, or have a different Type, what I do is loop through a sequence of expanding date ranges (StartDate-1, -2 etc) and also cycle through each Type looking for a match.
I've been reading that while loops aren't very efficient, so was wondering if there was a way to rewrite this nested loop into a CTE function.
I'm using SQL Server 2012.
Event List is just a temp table that has all the possible Types with an order to loop through.
My loop currently is:
WHILE #CurrBefore <= #Before and #CurrentAfter <= #After
BEGIN
SET #Row = 0
WHILE #Row <= #MaxRow
BEGIN
UPDATE P
SET P.ID = E.ID
FROM Event P
OUTER APPLY (SELECT TOP 1 E.Id, E.Type
FROM Episode E
WHERE E.User = P.User AND
E.Type = CASE WHEN #Row=0 THEN P.Event ELSE (SELECT Event FROM #EventList WHERE RN = #Row) END AND
P.Date BETWEEN E.StartDate-#CurrentBefore AND E.EndDate+#CurrentAfter
ORDER BY P.Date) E
WHERE P.ID = 0
INCREMENT #ROW CODE
END
INCREMENT #BEFORE/AFTER CODE
END
Sample Data:
IF OBJECT_ID('tempdb..#EventList') IS NOT NULL
BEGIN
DROP TABLE #EventList
CREATE TABLE #EventList(Event Varchar(50), RN INT);
INSERT INTO #EventList SELECT 'A', 1
INSERT INTO #EventList SELECT 'B', 2
INSERT INTO #EventList SELECT 'C', 3
INSERT INTO #EventList SELECT 'D', 4
INSERT INTO #EventList SELECT 'E', 5
INSERT INTO #EventList SELECT 'F', 6
END
CREATE TABLE dbo.Episode ([ID] INT, [Start] DateTime, [End] DateTime, [Type] varchar(1), [User] INT)
INSERT INTO [dbo].Episode ([ID], [Start], [End], [Type],[User])
VALUES
(1, '2018-07-01 10:00', '2018-07-02 14:00', 'A',10),
(2, '2018-07-05 6:00', '2018-07-06 13:00', 'A',11),
(3, '2018-07-03 9:00', '2018-07-04 8:00', 'B',10),
(4, '2018-07-02 15:00', '2018-07-03 7:00', 'B',12),
(5, '2018-07-01 1:00', '2018-07-02 8:00', 'C',13),
(6, '2018-07-01 6:00', '2018-07-01 8:00', 'D',11)
CREATE TABLE dbo.Event ([ID] INT, [Date] DateTime, [Type] varchar(1), [User] INT)
INSERT INTO [dbo].Event ([ID], [Date], [Type],[User])
VALUES
(0, '2018-07-01 12:00', 'A',10),
(0, '2018-07-05 15:00', 'A',11),
(0, '2018-07-03 13:00', 'C',10),
(0, '2018-07-10 9:00', 'B',12),
(0, '2018-07-01 5:00', 'C',10),
(0, '2018-07-01 10:00', 'D',11)
Expected result, Event now looks like this:
1 2018-07-01 12:00:00.000 A 10
2 2018-07-05 15:00:00.000 A 11
3 2018-07-03 13:00:00.000 C 10
0 2018-07-10 09:00:00.000 B 12
1 2018-07-01 05:00:00.000 C 10
6 2018-07-01 10:00:00.000 D 11
I don't know, if I fully got the logic, but this might help to get you running:
USE master;
GO
CREATE DATABASE TestDB
GO
USE TestDB;
GO
CREATE TABLE dbo.Episode ([ID] INT, [Start] DateTime, [End] DateTime, [Type] varchar(1), [User] INT)
INSERT INTO [dbo].Episode ([ID], [Start], [End], [Type],[User])
VALUES
(1, '2018-07-01 10:00', '2018-07-02 14:00', 'A',10),
(2, '2018-07-05 6:00', '2018-07-06 13:00', 'A',11),
(3, '2018-07-03 9:00', '2018-07-04 8:00', 'B',10),
(4, '2018-07-02 15:00', '2018-07-03 7:00', 'B',12),
(5, '2018-07-01 1:00', '2018-07-02 8:00', 'C',13),
(6, '2018-07-01 6:00', '2018-07-01 8:00', 'D',11)
CREATE TABLE dbo.[Event] ([ID] INT, [Date] DateTime, [Type] varchar(1), [User] INT)
INSERT INTO [dbo].[Event] ([ID], [Date], [Type],[User])
VALUES
(0, '2018-07-01 12:00', 'A',10),
(0, '2018-07-05 15:00', 'A',11),
(0, '2018-07-03 13:00', 'C',10),
(0, '2018-07-10 9:00', 'B',12),
(0, '2018-07-01 5:00', 'C',10),
(0, '2018-07-01 10:00', 'D',11)
GO
CREATE TABLE #EventList(Event Varchar(50), RN INT);
INSERT INTO #EventList VALUES ('A', 1),('B', 2),('C', 3),('D', 4),('E', 5),('F', 6);
WITH mathingEpisodes AS
(
SELECT ev.ID AS evID
,ev.[Date] AS evDate
,ev.[Type] AS evType
,ev.[User] AS evUser
,e1.RN AS evRN
,ep.ID AS epID
,ep.[Type] AS epType
,e2.RN AS epRN
FROM [Event] ev
LEFT JOIN Episode ep ON ev.[User]=ep.[User] AND ev.[Date] >= ep.[Start] AND ev.[Date] < ep.[End]
LEFT JOIN #EventList e1 ON ev.[Type]=e1.[Event]
LEFT JOIN #EventList e2 ON ep.[Type]=e2.[Event]
)
SELECT COALESCE(epID,Closest.ID) AS FittingEpisodeID
,me.evDate
,evType
,evUser
FROM mathingEpisodes me
OUTER APPLY(SELECT TOP 1 *
FROM Episode ep
CROSS APPLY(SELECT ABS(DATEDIFF(SECOND,me.evDate,ep.[Start])) AS DiffToStart
,ABS(DATEDIFF(SECOND,me.evDate,ep.[End])) AS DiffToEnd) Diffs
CROSS APPLY(SELECT CASE WHEN DiffToStart<DiffToEnd THEN DiffToStart ELSE DiffToEnd END AS Smaller) Diffs2
WHERE ep.[User] = me.evUser
AND me.epID IS NULL
ORDER BY Diffs2.Smaller
) Closest
ORDER BY evDate;
GO
USE master;
GO
DROP DATABASE TestDB;
GO
DROP TABLE #EventList
GO
The result
1 2018-01-07 05:00:00.000 C 10
6 2018-01-07 10:00:00.000 D 11
1 2018-01-07 12:00:00.000 A 10
3 2018-03-07 13:00:00.000 C 10
2 2018-05-07 15:00:00.000 A 11
4 2018-10-07 09:00:00.000 B 12
Some explanation
In the first cte I try to find fitting episodes (same user and date within range).
The second cte will compute the closest Episode for the same user in all cases, where the first cte did not succeed.
The only difference for this sample is the event for userId=12. My logic will bind this to the closest episode of this user (ID=4), while your expected output shows a zero in this place.
Anyway, my solution is fully set-based, therefore faster than a loop, and should be rather close to your needs. Try to adapt it...
UPDATE Some more thoughts...
I did not get the ghist of your #EventList... I bound the results into the set (you can make it visible by using SELECT * instead of the explicit column list. But this is - assumably - not what you meant...

How to write a case when statement when there are overlaps in T-SQL

I have a table like this
How can I group it to this
Small is the sum of the count when Count <25; Large is the sum of the count when Count>=25; Total is the sum of all counts.
Try it like this...
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
DROP TABLE #TestData;
CREATE TABLE #TestData (
ID INT NOT NULL PRIMARY KEY,
nCount int NOT NULL
);
INSERT #TestData (ID, nCount) VALUES
(1, 10), (2, 15), (3, 22), (4, 23),
(5, 25), (6, 27), (7, 30);
--=====================================
WITH
cte_Totals AS (
SELECT
Total = SUM(td.nCount),
Small = SUM(CASE WHEN td.nCount < 25 THEN td.nCount ELSE 0 END),
Large = SUM(CASE WHEN td.nCount >= 25 THEN td.nCount ELSE 0 END)
FROM
#TestData td
)
SELECT
x.[Group],
x.[Count]
FROM
cte_Totals t
CROSS APPLY (VALUES (1, 'Total', t.Total), (2, 'Small', t.Small), (3, 'Large', t.Large) ) x (SortBy, [Group],[Count])
ORDER BY
x.SortBy;
Results...
Group Count
----- -----------
Total 152
Small 70
Large 82
HTH,
Jason
The simplest way is to use CASE:
SELECT
SUM(Count) as Total,
SUM(CASE WHEN Count < 25 THEN Count ELSE 0 END) as Small,
SUM(CASE WHEN Count >= 25 THEN Count ELSE 0 END) as Large
FROM table
Late answer (keep the accepted as is), but I did want to introduce a concept which may be more helpful down the line.
I maintain a generic Tier Table. The following is a simplified example, but you can take the aggregation tiers out of the code, and put it in a table... things change, and you can serve multiple masters.
Sample Data
Declare #YourTable table (ID int,[Count] int)
Insert Into #YourTable values
(1, 10), (2, 15), (3, 22), (4, 23), (5, 25), (6, 27), (7, 30)
Declare #Tier table (Tier varchar(50),Seq int,Title varchar(50),R1 int,R2 int)
Insert Into #Tier values
('MyGroup',1,'Total',0,99999)
,('MyGroup',2,'Small',0,25)
,('MyGroup',3,'Large',25,99999)
The Actual Query
Select T.Title
,[Count] = sum(D.[Count])
From #Tier T
Join #YourTable D on (T.Tier='MyGroup' and D.Count >= T.R1 and D.Count<T.R2)
Group By T.Title,T.Seq
Order By T.Seq
Returns
Title Count
Total 152
Small 70
Large 82
EDIT - There are many ways you can construct this
Example
Declare #YourTable table (ID varchar(50),[Count] int)
Insert Into #YourTable values
('Tywin', 10), ('Tywin', 15), ('Tyrion', 22), ('Bran', 23), ('Ned', 25), ('John', 27), ('Robb', 30)
Declare #Tier table (Tier varchar(50),Seq int,Title varchar(50),R1 int,R2 int,C1 varchar(50),C2 varchar(50))
Insert Into #Tier values
('MyGroup',1,'Total' ,null,null,'a','z')
,('MyGroup',2,'Group 1',null,null,'Tywin,Tyrion',null)
,('MyGroup',3,'Group 2',null,null,'Bran,Ned,John,Robb',null)
Select T.Title
,[Count] = sum(D.[Count])
From #Tier T
Join #YourTable D on T.Tier='MyGroup' and (D.ID between C1 and C2 or patindex('%,'+D.ID+',%',','+C1+',')>0)
Group By T.Title,T.Seq
Order By T.Seq
Returns
Title Count
Total 152
Group 1 47
Group 2 105

In T-SQL is there a built-in command to determine if a number is in a range from another table

This is not a homework question.
I'm trying to take the count of t-shirts in an order and see which price range the shirts fall into, depending on how many have been ordered.
My initial thought (I am brand new at this) was to ask another table if count > 1st price range's maximum, and if so, keep looking until it's not.
printing_range_max printing_price_by_range
15 4
24 3
33 2
So for example here, if the order count is 30 shirts they would be $2 each.
When I'm looking into how to do that, it looks like most people are using BETWEEN or IF and hard-coding the ranges instead of looking in another table. I imagine in a business setting it's best to be able to leave the range in its own table so it can be changed more easily. Is there a good/built-in way to do this or should I just write it in with a BETWEEN command or IF statements?
EDIT:
SQL Server 2014
Let's say we have this table:
DECLARE #priceRanges TABLE(printing_range_max tinyint, printing_price_by_range tinyint);
INSERT #priceRanges VALUES (15, 4), (24, 3), (33, 2);
You can create a table with ranges that represent the correct price. Below is how you would do this in pre-2012 and post-2012 systems:
DECLARE #priceRanges TABLE(printing_range_max tinyint, printing_price_by_range tinyint);
INSERT #priceRanges VALUES (15, 4), (24, 3), (33, 2);
-- post-2012 using LAG
WITH pricerange AS
(
SELECT
printing_range_min = LAG(printing_range_max, 1, 0) OVER (ORDER BY printing_range_max),
printing_range_max,
printing_price_by_range
FROM #priceRanges
)
SELECT * FROM pricerange;
-- pre-2012 using ROW_NUMBER and a self-join
WITH prices AS
(
SELECT
rn = ROW_NUMBER() OVER (ORDER BY printing_range_max),
printing_range_max,
printing_price_by_range
FROM #priceRanges
),
pricerange As
(
SELECT
printing_range_min = ISNULL(p2.printing_range_max, 0),
printing_range_max = p1.printing_range_max,
p1.printing_price_by_range
FROM prices p1
LEFT JOIN prices p2 ON p1.rn = p2.rn+1
)
SELECT * FROM pricerange;
Both queries return:
printing_range_min printing_range_max printing_price_by_range
------------------ ------------------ -----------------------
0 15 4
15 24 3
24 33 2
Now that you have that you can use BETWEEN for your join. Here's the full solution:
-- Sample data
DECLARE #priceRanges TABLE
(
printing_range_max tinyint,
printing_price_by_range tinyint
-- if you're on 2014+
,INDEX ix_xxx NONCLUSTERED(printing_range_max, printing_price_by_range)
-- note: second column should be an INCLUDE but not supported in table variables
);
DECLARE #orders TABLE
(
orderid int identity,
ordercount int
-- if you're on 2014+
,INDEX ix_xxy NONCLUSTERED(orderid, ordercount)
-- note: second column should be an INCLUDE but not supported in table variables
);
INSERT #priceRanges VALUES (15, 4), (24, 3), (33, 2);
INSERT #orders(ordercount) VALUES (10), (20), (25), (30);
-- Solution:
WITH pricerange AS
(
SELECT
printing_range_min = LAG(printing_range_max, 1, 0) OVER (ORDER BY printing_range_max),
printing_range_max,
printing_price_by_range
FROM #priceRanges
)
SELECT
o.orderid,
o.ordercount,
--p.printing_range_min,
--p.printing_range_max
p.printing_price_by_range
FROM pricerange p
JOIN #orders o ON o.ordercount BETWEEN printing_range_min AND printing_range_max
Results:
orderid ordercount printing_price_by_range
----------- ----------- -----------------------
1 10 4
2 20 3
3 25 2
4 30 2
Now that we have that we can

get Common rows

I have a Table :
Subject_ID StudyPlan_ID
271 2
279 2
276 2
279 8
271 8
267 9
279 9
I want to find the common Subject_ID between StudyPlan_ID so it's 279 using SqlServer 2008
So please any help.
If I understand it correctly, you mean find the Subject_ID that is linked to every StudyPlan_ID.
DECLARE #Data TABLE(Subject_ID int, StudyPlan_ID int)
INSERT INTO #Data
VALUES
(271, 2),
(279, 2),
(276, 2),
(279, 8),
(271, 8),
(267, 9),
(279, 9)
SELECT Subject_ID
FROM #Data AS a
GROUP BY Subject_ID
HAVING COUNT(Distinct StudyPlan_ID) = (SELECT COUNT(Distinct StudyPlan_ID) FROM #Data)

Resources