Get start and End location and Date Sql server 2012 - sql

i want to convert this query to start GRP to End Grp and Start Date to End date.
select * from (
select z.ZoneGroupId, zs.ObjectId,z.Name,case when zs.Inside=0 then 'Left' else 'Entered' end Crossing ,zs.TimeFirst
from zs join
z on zs.Zid=z.Zid
where zs.ObjectId=5696 and z.ZoneGroupId in (1095,1096) and convert(date,zs.TimeFirst)>='2016/07/01' ) s
where (ZoneGroupId=1096 and s.Crossing='Entered') or (ZoneGroupId=1095 and s.Crossing='Left')
2 table involve in query
table Z
Zid(int) Name(varchar) ZoneGroupId (int)
59 Oil 1095
60 ENR 1096
61 NRL 1096
table Zs
zsid(int) zid(int) ObjectId(int) Timefirst(datetime) Inside(boolan)
1 60 1988 2016-07-01 00:39 1
2 59 1988 2016-07-05 15:47 0
3 61 1988 2016-07-06 22:54 1
4 59 1988 2016-07-09 13:40 0
5 60 1988 2016-07-10 07:58 1
6 59 1988 2016-07-13 10:30 0
7 59 1988 2016-09-10 10:21 0
8 59 1990 2016-07-05 15:47 0
9 61 1990 2016-07-06 22:54 1
the result which i required from above query
ZoneGroupId ObjectId Name Crossing TimeFirst
1096 1988 ENR Entered 2016-07-01 00:39
1095 1988 Oil Left 2016-07-05 15:47
1096 1988 NRL Entered 2016-07-06 22:54
1095 1988 Oil Left 2016-07-09 13:40
1096 1988 ENR Entered 2016-07-10 07:58
1095 1988 Oil Left 2016-07-13 10:30
1095 1988 Oil Left 2016-09-10 10:21
1095 1990 Oil Left 2016-07-05 15:47
1096 1990 NRL Entered 2016-07-06 22:54
required result
ObjectId StartName StartDate EndName EndDate
1988 Null Null ENR 2016-07-01 00:39
1988 Oil 2016-07-05 15:47 NRL 2016-7-06 22:54
1988 Oil 2016-07-09 13:40 ENR 2016-07-10 07:58
1988 Oil 2016-07-13 10:30 Null Null
1988 Oil 2016-09-10 10:21 Null Null
1988 Oil 2016-07-05 15:47 NRL 2016-7-06 22:54

First your sample data - please include this in your question in future.
declare #z table (Zid int, Name nvarchar(3), ZoneGroupId int);
insert into #z values
(59, 'Oil', 1095),
(60, 'ENR', 1096),
(61, 'NRL', 1096);
declare #zs table(zsid int, zid int, ObjectId int, Timefirst datetime, Inside bit);
insert into #zs values
( 1, 60, 1988, '2016-07-01 00:39', 1),
( 2, 59, 1988, '2016-07-05 15:47', 0 ),
( 3, 61, 1988, '2016-07-06 22:54', 1 ),
( 4, 59, 1988, '2016-07-09 13:40', 0 ),
( 5, 60, 1988, '2016-07-10 07:58', 1 ),
( 6, 59, 1988, '2016-07-13 10:30', 0 ),
( 7, 59, 1988, '2016-09-10 10:21', 0 ),
( 8, 59, 1990, '2016-07-05 15:47', 0 ),
( 9, 61, 1990, '2016-07-06 22:54', 1 );
Then, I split the data into 2 tables, left and entered by using common-table-expressions. Add in a row number to put them in order by time.
Join the tables back together with a full outer join (to get all rows from both sides). The specify the following criteria on the join:
ObjectIds match
Entered.TimeFirst is the smallest one that is bigger than Left.TimeFirst
Left.TimeFirst is the largest one that is smaller than entered.TimeFirst
I also added an order by for clarity. Here is the query.
with entered as (
select z.ZoneGroupId
, zs.ObjectId
, z.Name
, 'Entered' Crossing
, zs.TimeFirst
, ROW_NUMBER() over (partition by ObjectID order by zs.TimeFirst) row_no
from #zs zs
inner join #z z on zs.Zid=z.Zid
where zs.Inside <> 0 and (z.ZoneGroupId = 1096 and convert(date,zs.TimeFirst)>='2016/07/01')
), [left] as (
select z.ZoneGroupId
, zs.ObjectId
, z.Name
, 'Left' Crossing
, zs.TimeFirst
, ROW_NUMBER() over (partition by ObjectID order by zs.TimeFirst) row_no
from #zs zs
inner join #z z on zs.Zid=z.Zid
where zs.Inside = 0 and (z.ZoneGroupId = 1095 and convert(date,zs.TimeFirst)>='2016/07/01')
)
select *
from [left]
full outer join entered
on entered.row_no = (select MIN(row_no) from entered e
where e.TimeFirst > [left].TimeFirst
and e.ObjectId = [left].ObjectId)
and [left].row_no = (select max(row_no) from [left] l
where l.TimeFirst < entered.TimeFirst
and l.ObjectId = entered.ObjectId)
and [left].ObjectId = [entered].ObjectId
order by isnull([left].ObjectId,entered.ObjectId), ISNULL([left].TimeFirst,entered.TimeFirst)

Related

Selecting records from slowly changing table with a set of dates

I have a slowly changing table,a new row is created each time any of the source fields are changed. Some metadata is added to show when that version was valid. This is a simplified example(dates are dd/mm/yyyy format) that doesn't show the fields which have changed.
Startdate
Enddate
Currentrecord
unique id
serial_number
15/12/2020
31/12/2020
0
1
2345
15/12/2020
8/3/2021
0
2
1234
19/9/2020
15/2/2021
0
3
2345
15/12/2020
8/3/2021
0
4
3456
9/3/2021
10/3/2021
0
5
3456
16/2/2021
10/3/2021
0
6
2345
9/3/2021
26/3/2021
0
7
1234
27/3/2021
2/5/2021
0
8
1234
11/3/2021
17/5/2021
0
9
3456
3/3/2021
27/4/2021
0
10
4567
20/1/2021
7/4/2021
0
11
5678
3/5/2021
30/6/2021
1
12
1234
25/5/2021
31/5/2021
0
13
2345
8/4/2021
22/5/2021
0
14
5678
1/6/2021
26/6/2021
0
15
2345
18/5/2021
3/6/2021
0
16
3456
27/6/2021
2/8/2021
0
17
2345
28/4/2021
28/6/2021
0
18
4567
23/5/2021
6/9/2021
0
19
5678
4/6/2021
28/6/2021
0
20
3456
29/6/2021
25/7/2021
0
21
3456
3/8/2021
31/12/9999
1
22
2345
26/7/2021
31/12/9999
1
23
3456
15/10/2021
31/12/9999
1
24
4567
7/9/2021
1/11/2021
0
25
5678
22/9/2021
10/11/2021
0
26
6789
2/11/2021
16/11/2021
0
27
5678
17/11/2021
21/11/2021
0
28
5678
15/7/2021
31/12/9999
1
29
7891
22/11/2021
31/12/9999
1
30
5678
26/11/2021
31/12/9999
1
31
6789
15/6/2021
31/12/9999
1
32
8912
There is only one record for each serial_number for any given point in time (i.e. the dates ranges will not overlap for identical serial_numbers) but there might be gaps between episodes for a some serial_numbers (representing something leaving and returning after a gap in service).
I want to supply an arbitrary list of datetimes, say midnight on 01/01/2021, 15/03/2021, 27/05/2021. 23/10/2021. I want to return a set of records, containing every record which was in effect on each of the dates, with each row labelled with the date it was selected by. So the above example should return this.
date
unique id
serial_number
1/1/2021
2
1234
1/1/2021
3
2345
1/1/2021
4
3456
15/3/2021
7
1234
15/3/2021
9
3456
15/3/2021
10
4567
15/3/2021
11
5678
27/5/2021
12
1234
27/5/2021
13
2345
27/5/2021
16
3456
27/5/2021
18
4567
27/5/2021
19
5678
23/10/2021
22
2345
23/10/2021
23
3456
23/10/2021
24
4567
23/10/2021
25
5678
23/10/2021
26
6789
23/10/2021
29
7891
23/10/2021
32
8912
I can see how to do this with a cursor, stepping through each date putting them into a variable and using something like
select #date, [unique id], serial_number
from example
where #date between start_date and end_date
to get the rows.
I can’t work out a pattern that would do it in a set based approach. My preferred SQL version is TSQL. Sorry as this is almost certainly a repeat, but I can't find a form of words that hits a worked example.
You can use a temporary table to accomplish this.
CREATE TABLE #RequestedDates([Date] DATE)
You insert your dates you want into a temporary table.
INSERT INTO #RequestedDates([Date])
VALUES ('2021-01-01'), ('2021-03-15') /*Other dates*/
And then you join with the temporary table and use the between clause to get the valid results.
SELECT rd.[Date]
, t.UniqueId
, t.SerialNumber
FROM MyTable t
INNER JOIN #RequestedDates rd on rd.[Date] BETWEEN t.StartDate AND t.EndDate
ORDER BY rd.[Date]
, t.UniqueId
, t.SerialNumber
You can join to VALUES with the dates you need.
Then join the datetimes on the range.
SELECT
datetimes.dt as [date]
, t.[unique id]
, t.serial_number
FROM example t
JOIN (VALUES
(cast('2021-01-01 00:00:00' as datetime)),
('2021-03-15 00:00:00'),
('2021-05-27 00:00:00'),
('2021-10-23 00:00:00')
) datetimes(dt)
ON datetimes.dt >= t.start_date
AND datetimes.dt <= t.end_date
ORDER BY datetimes.dt, t.[unique id], t.serial_number

How to join two tables based on conditon in sql?

I need to Join two table with respective to two columns
Stu_id (Table 1) - Stu_id (Table 2)
Perf_yr(Table 1) - yr_month (Table 2)
perf_yr starts on every year Sept to Aug.
Perf_yr should match the yr_month based on Perf_yr start and end Month
Table 1
Stu_id Roll_No Avg_marks Perf_yr
1 100244 72 2017
2 200255 62 2018
3 100246 68 2019
Table 2
Stu_id Subject Marks yr_month
1 Maths 70 201609
1 Science 69 201701
1 Social 74 201712
2 Maths 60 201709
2 Science 61 201801
2 Social 62 201808
3 Maths 65 201810
3 Science 64 201912
3 Social 72 201902
Output
Stu_id Roll_No Avg_marks Perf_yr Subject Marks yr_month
1 100244 72 2017 Maths 70 201609
1 100244 72 2017 Science 70 201701
2 200255 62 2018 Maths 60 201709
2 200255 62 2018 Science 61 201801
2 200255 62 2018 Social 62 201808
3 100246 68 2019 Maths 65 201810
3 100246 68 2019 Science 64 201912
3 100246 68 2019 Social 72 201902
I TRIED :
SELECT A.*, B.* FROM
(SELECT * FROM TABLE1 )A
LEFT JOIN
(SELECT * FROM TABLE)B
ON
A.Stu_id = B.Stu_id
AND
A.Perf_yr = B.Yr_Month
BUT IT WONT GIVE THE DESIRED RESULT BECAUSE THE CONDITION IS NOT SATISFYING THE PERF YR START AND END DATE .
You need to parse eg 201609 as a date, add 4 months to it, then match it to the year from the other table. Adding 4 months converts a date range 201609-201708 into being 201701-201712 - we only care about the year part:
SELECT * FROM
t1
INNER JOIN t2
ON
t1.stu_id = t2.stu_id AND
t1.Perf_yr = EXTRACT(year FROM ADD_MONTHS(TO_DATE(t2.yr_month, 'YYYYMM'), 4))
This is oracle. The same logic will work for SQLS, you'll just need to adjust the functions used-
CONVERT(date, t2.yr_month+'01', 112) -- Convert yyyymmdd to a date
DATEADD(month, x, 4) -- add 4 months to x
YEAR(x) -- extract year from date x

Creating a date table for multiple primary keys between a specified open and close date for each primary key

Good day,
I have been wracking my brain for the past few hours to build a table that looks like this:
I have about 33 000 entries that have their own opening and closing dates. I am trying to build a table that puts each of the dates (including the opening and closing dates) in a single row per entry (JOURNAL_NO) below each other in SQL Server Management Studio.
I need to run a check on each day for each entry and I have tried to build the table by making use of my primary table and a calendar table that I created. Please refer to the code below (I have also included the calendar code below this):
Code I'm trying to get working:
DECLARE #START_DATE date = '2014-01-01',
#END_DATE date = '2018-12-31'
WHILE #START_DATE <= #END_DATE
BEGIN
SET #START_DATE = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY N) - 1, #START_DATE)
SELECT LO_MASTER.JOURAL_NO, --(33000 entries)
LO_MASTER.START_DATE, -- each entry has a different opening date
CAL.DATE -- date in calendar table
CAL.DAY AS DATEPART(DAY,[DATE]),
CAL.MONTH AS DATEPART(MONTH,[DATE]),
CAL.YEAR AS DATEPART(YEAR,[DATE]), -- these will be the date parts between the OPEN_DATE & CLOSE_DATE for each account
LO_MASTER.END_DATE -- each entry has a different closing date
FROM [dbo.][F1_master] as LO_MASTER
inner join CALENDAR_TABLE as CAL LO_MASTER.DATE = CAL.DATE
WHERE CAL.DATE between LO_MASTER.START_DATE and LO_MASTER.END_DATE -- range where the fields from table b need to be populated for each account
END
Table definition:
USE [master]
GO
/****** Object: Table [dbo].[dummy_data] Script Date: 11/02/2019 07:31:59 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[dummy_data](
[JOURNAL_NO] [int] NULL,
[START_DATE] [date] NULL,
[END_DATE] [date] NULL,
[DURATION_ON_BOOK] [int] NULL
) ON [PRIMARY]
GO
Sample data:
JOURNAL_NO START_DATE END_DATE DURATION_ON_BOOK
101388 15/01/2014 01/01/2017 35
101499 14/01/2014 21/01/2017 36
101502 17/01/2014 17/02/2017 53
101876 06/01/2014 30/09/2017 35
101877 06/01/2014 24/01/2018 60
101878 07/01/2014 28/02/2018 60
101879 07/01/2014 19/01/2017 50
101881 07/01/2014 16/04/2018 58
101882 07/01/2014 13/11/2018 58
101883 08/01/2014 17/11/2016 59
101884 13/01/2014 26/06/2018 60
101886 13/01/2014 20/12/2016 59
101887 13/01/2014 13/12/2016 60
101888 13/01/2014 11/09/2017 43
101889 14/01/2014 07/12/2017 68
101890 14/01/2014 02/01/2018 58
101892 15/01/2014 21/02/2017 38
101893 17/01/2014 15/09/2017 64
101894 21/01/2014 02/02/2017 40
101896 21/01/2014 09/05/2016 38
101904 27/01/2014 21/12/2016 69
101906 27/01/2014 11/11/2016 36
101966 07/01/2014 10/03/2017 36
101967 07/01/2014 09/07/2018 40
102073 07/01/2014 15/09/2016 60
102074 13/01/2014 20/06/2017 40
102076 14/01/2014 15/06/2016 40
102077 15/01/2014 01/12/2016 60
102079 17/01/2014 12/10/2016 40
102081 21/01/2014 20/04/2017 40
102082 23/01/2014 14/02/2017 38
102234 02/01/2014 20/09/2017 46
102236 08/01/2014 05/05/2017 36
102237 15/01/2014 23/08/2017 68
102240 21/01/2014 27/02/2018 50
102241 21/01/2014 25/08/2016 37
102253 06/01/2014 26/10/2016 27
102254 07/01/2014 17/11/2016 61
102255 07/01/2014 26/04/2017 38
102256 10/01/2014 11/10/2017 42
102258 13/01/2014 18/05/2017 26
102263 17/01/2014 29/11/2018 74
102265 20/01/2014 31/10/2016 31
102372 06/01/2014 25/04/2017 35
102463 09/01/2014 25/08/2017 69
102464 09/01/2014 01/07/2016 26
102465 15/01/2014 24/12/2016 36
102530 06/01/2014 24/12/2017 48
102531 07/01/2014 28/08/2017 76
102532 09/01/2014 21/06/2017 39
Could anyone please assist me? I haven't been coding that long and my troubleshoot attempts aren't providing any correct solutions. It would be greatly appreciated.
Thank you.
Using a tally table this is pretty simple. I keep one on my system as a view that is lightning fast because it doesn't need any disc I/O at all. It look amazingly similar to what you had posted initially.
create View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
GO
Next we need some sample data. I stripped this down to just a couple of journals to demonstrate.
declare #dummy_data table
(
JOURNAL_NO int
, START_DATE datetime
, END_DATE datetime
, DURATION_ON_BOOK int
)
insert #dummy_data values
(101388, '20140115', '20170101', 35)
, (101499, '20160114', '20170121', 36)
Now we just need to leverage the power of a tally table with your data. This is what your query might look like. No need for loops, just some basic date math.
select *
, EachDay = dateadd(day, t.N - 1, d.Start_Date)
, MyDay = t.N
, MyMonth = datediff(month, d.Start_DATE, dateadd(day, t.N - 1, d.Start_Date)) + 1
, MyYear = datepart(year, dateadd(day, t.N - 1, d.Start_Date))
from #dummy_data d
join cteTally t on t.N <= datediff(day, d.START_DATE, d.END_DATE) + 1

SQL Server 2008 Pivot, no Aggregation, complex data

I've seen a lot of "Pivot, No Agg" posts, but all of them seem to involve some pretty simple data to pivot, so the solutions work fairly well and easily. But how about when the data isn't as simple?
I'd like to turn this:
wwnID Tenant WeekOfTheMonth ReportingDate TotalEmployeesPerBranch TotalOpenCount TotalClosedCount OpenCount_TitleAndEscrow ClosedCount_TitleAndEscrow OpenCount_EscrowOnly ClosedCount_EscrowOnly OpenCount_PreListingTask ClosedCount_PreListingTask OFPE CFPE OpenCount_TitleOnly ClosedCount_TitleOnly CurrentBusinessDay TotalBusinessDaysMTD ReportingDateId CreatedDate
----------- -------------------------------------------------- -------------- ----------------------- --------------------------------------- -------------- ---------------- ------------------------ -------------------------- -------------------- ---------------------- ------------------------ -------------------------- --------------------------------------- --------------------------------------- ------------------- --------------------- ------------------ -------------------- --------------- -----------------------
3 King 1 2014-08-08 00:00:00.000 144.00 235 0 137 0 64 0 34 0 4.81 0.00 270 0 7 21 411 2014-09-05 08:53:11.313
5 King 2 2014-08-15 00:00:00.000 150.00 399 0 224 0 112 0 63 0 4.62 0.00 524 0 12 21 412 2014-09-05 08:53:19.573
7 King 3 2014-08-22 00:00:00.000 150.00 584 0 335 0 159 0 90 0 4.76 0.00 721 0 17 21 413 2014-09-05 08:53:26.980
9 King 4 2014-08-31 00:00:00.000 150.00 797 0 436 0 226 0 135 0 5.18 0.00 946 0 21 21 414 2014-09-05 08:53:35.593
4 Pierce 1 2014-08-08 00:00:00.000 21.00 85 0 31 0 39 0 15 0 12.00 0.00 54 0 7 21 411 2014-09-05 08:53:11.670
6 Pierce 2 2014-08-15 00:00:00.000 22.00 160 0 62 0 74 0 24 0 12.41 0.00 83 0 12 21 412 2014-09-05 08:53:20.000
8 Pierce 3 2014-08-22 00:00:00.000 22.00 222 0 82 0 107 0 33 0 12.41 0.00 127 0 17 21 413 2014-09-05 08:53:27.407
10 Pierce 4 2014-08-31 00:00:00.000 23.00 272 0 99 0 130 0 43 0 10.96 0.00 159 0 21 21 414 2014-09-05 08:53:36.063
into this:
Data Types Week 1 Week 2 Week 3 Week 4
------------------------------- ----------- ----------- ----------- -----------
Tenant King King King King
ReportingDate 8/8/2014 8/15/2014 8/22/2014 8/31/2014
TotalEmployeesPerBranch 144 150 150 150
TotalOpenCount 235 399 584 797
TotalClosedCount 0 0 0 0
OpenCount_TitleAndEscrow 137 224 335 436
ClosedCount_TitleAndEscrow 0 0 0 0
OpenCount_EscrowOnly 64 112 159 226
ClosedCount_EscrowOnly 0 0 0 0
OpenCount_PreListingTask 34 63 90 135
ClosedCount_PreListingTask 0 0 0 0
OFPE 4.81 4.62 4.76 5.18
CFPE 0 0 0 0
OpenCount_TitleOnly 270 524 721 946
ClosedCount_TitleOnly 0 0 0 0
CurrentBusinessDay 7 12 17 21
TotalBusinessDaysMTD 21 21 21 21
ReportingDateId 411 412 413 414
CreatedDate 9/5/2014 9/5/2014 9/5/2014 9/5/2014
Tenant Pierce Pierce Pierce Pierce
ReportingDate 8/8/2014 8/15/2014 8/22/2014 8/31/2014
TotalEmployeesPerBranch 21 22 22 23
TotalOpenCount 85 160 222 272
TotalClosedCount 0 0 0 0
OpenCount_TitleAndEscrow 31 62 82 99
ClosedCount_TitleAndEscrow 0 0 0 0
OpenCount_EscrowOnly 39 74 107 130
ClosedCount_EscrowOnly 0 0 0 0
OpenCount_PreListingTask 15 24 33 43
ClosedCount_PreListingTask 0 0 0 0
OFPE 12 12.41 12.41 10.96
CFPE 0 0 0 0
OpenCount_TitleOnly 54 83 127 159
ClosedCount_TitleOnly 0 0 0 0
CurrentBusinessDay 7 12 17 21
TotalBusinessDaysMTD 21 21 21 21
ReportingDateId 411 412 413 414
CreatedDate 9/5/2014 9/5/2014 9/5/2014 9/5/2014
I've tried several methods of pivoting, and none of them seem to do the trick, but if anyone out there knows a way to do it, that'd be fantastic!
Thanks ahead of time!
UPDATE
This works beautifully! (initial variable declarations are for the where clause toward the end)
DECLARE #ReportDate DATETIME = '2014-08-31';
DECLARE #RepDateId INT = ( SELECT MAX([WRD].[ReportingDateID])
FROM [SMS].[dbo].[WSOBReportingDates] AS WRD
WHERE ( [WRD].[ReportingDate] <= #ReportDate )
AND ( [WRD].[Submitted] = 1 ) );
DECLARE #WSOBRepDate DATETIME = ( SELECT [WRD].[ReportingDate]
FROM [SMS].[dbo].[WSOBReportingDates] AS WRD
WHERE [WRD].[ReportingDateID] = #RepDateId );
DECLARE #WSOBStartDate DATETIME = DATEADD(mm, DATEDIFF(mm, 0, #WSOBRepDate), 0);
SELECT Datatype
, MAX(CASE WHEN WeekOfTheMonth = 1 THEN value ELSE '0' END) Week1
, MAX(CASE WHEN WeekOfTheMonth = 2 THEN value ELSE '0' END) Week2
, MAX(CASE WHEN WeekOfTheMonth = 3 THEN value ELSE '0' END) Week3
, MAX(CASE WHEN WeekOfTheMonth = 4 THEN value ELSE '0' END) Week4
FROM ( SELECT WeekOfTheMonth
, DataType
, Value
, SortOrder
, Sequence = ROW_NUMBER() OVER ( PARTITION BY WeekOfTheMonth ORDER BY wwnId )
FROM [dbo].[SSRS_WSOBWeeklyNumbers] AS SWWN
CROSS APPLY ( SELECT 'Tenant'
, [SWWN].[Tenant]
, 1
UNION ALL
SELECT 'ReportingDate'
, CONVERT(VARCHAR(10), [SWWN].[ReportingDate], 120)
, 2
UNION ALL
SELECT 'TotalEmployeesPerBranch'
, CAST([SWWN].[TotalEmployeesPerBranch] AS VARCHAR(10))
, 3
UNION ALL
SELECT 'TotalOpenCount'
, CAST([SWWN].[TotalOpenCount] AS VARCHAR(10))
, 4
UNION ALL
SELECT 'TotalClosedCount'
, CAST([SWWN].[TotalClosedCount] AS VARCHAR(10))
, 5
UNION ALL
SELECT 'OpenCount_TitleAndEscrow'
, CAST([SWWN].[OpenCount_TitleAndEscrow] AS VARCHAR(10))
, 6
UNION ALL
SELECT 'ClosedCount_TitleAndEscrow'
, CAST([SWWN].[ClosedCount_TitleAndEscrow] AS VARCHAR(10))
, 7
UNION ALL
SELECT 'OpenCount_EscrowOnly'
, CAST([SWWN].[OpenCount_EscrowOnly] AS VARCHAR(10))
, 8
UNION ALL
SELECT 'ClosedCount_EscrowOnly'
, CAST([SWWN].[ClosedCount_EscrowOnly] AS VARCHAR(10))
, 9
UNION ALL
SELECT 'OpenCount_PreListingTask'
, CAST([SWWN].[OpenCount_PreListingTask] AS VARCHAR(10))
, 10
UNION ALL
SELECT 'ClosedCount_PreListingTask'
, CAST([SWWN].[ClosedCount_PreListingTask] AS VARCHAR(10))
, 11
UNION ALL
SELECT 'OFPE'
, CAST([SWWN].[OFPE] AS VARCHAR(10))
, 12
UNION ALL
SELECT 'CFPE'
, CAST([SWWN].[CFPE] AS VARCHAR(10))
, 13
UNION ALL
SELECT 'OpenCount_TitleOnly'
, CAST([SWWN].[OpenCount_TitleOnly] AS VARCHAR(10))
, 14
UNION ALL
SELECT 'ClosedCount_TitleOnly'
, CAST([SWWN].[ClosedCount_TitleOnly] AS VARCHAR(10))
, 15
UNION ALL
SELECT 'CurrentBusinessDay'
, CAST([SWWN].[CurrentBusinessDay] AS VARCHAR(10))
, 16
UNION ALL
SELECT 'TotalBusinessDaysForMonth'
, CAST([SWWN].[TotalBusinessDaysMTD] AS VARCHAR(10))
, 17
UNION ALL
SELECT 'ReportingDateId'
, CAST([SWWN].[ReportingDateId] AS VARCHAR(10))
, 18
UNION ALL
SELECT 'CreatedDate'
, CAST([SWWN].[CreatedDate] AS VARCHAR(10))
, 19 ) c ( DataType, Value, SortOrder )
WHERE [SWWN].[ReportingDate] BETWEEN #WSOBStartDate AND #ReportDate ) d
GROUP BY DataType
, Sequence
, SortOrder
ORDER BY Sequence
, SortOrder;
and results in:
Datatype Week1 Week2 Week3 Week4
-------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------------------------------------
Tenant King King King King
ReportingDate 2014-08-08 2014-08-15 2014-08-22 2014-08-31
TotalEmployeesPerBranch 144.00 150.00 150.00 150.00
TotalOpenCount 235 399 584 797
TotalClosedCount 0 0 0 0
OpenCount_TitleAndEscrow 137 224 335 436
ClosedCount_TitleAndEscrow 0 0 0 0
OpenCount_EscrowOnly 64 112 159 226
ClosedCount_EscrowOnly 0 0 0 0
OpenCount_PreListingTask 34 63 90 135
ClosedCount_PreListingTask 0 0 0 0
OFPE 4.81 4.62 4.76 5.18
CFPE 0.00 0.00 0.00 0.00
OpenCount_TitleOnly 270 524 721 946
ClosedCount_TitleOnly 0 0 0 0
CurrentBusinessDay 7 12 17 21
TotalBusinessDaysForMonth 21 21 21 21
ReportingDateId 411 412 413 414
CreatedDate Sep 5 201 Sep 5 201 Sep 5 201 Sep 5 201
Tenant Pierce Pierce Pierce Pierce
ReportingDate 2014-08-08 2014-08-15 2014-08-22 2014-08-31
TotalEmployeesPerBranch 21.00 22.00 22.00 23.00
TotalOpenCount 85 160 222 272
TotalClosedCount 0 0 0 0
OpenCount_TitleAndEscrow 31 62 82 99
ClosedCount_TitleAndEscrow 0 0 0 0
OpenCount_EscrowOnly 39 74 107 130
ClosedCount_EscrowOnly 0 0 0 0
OpenCount_PreListingTask 15 24 33 43
ClosedCount_PreListingTask 0 0 0 0
OFPE 12.00 12.41 12.41 10.96
CFPE 0.00 0.00 0.00 0.00
OpenCount_TitleOnly 54 83 127 159
ClosedCount_TitleOnly 0 0 0 0
CurrentBusinessDay 7 12 17 21
TotalBusinessDaysForMonth 21 21 21 21
ReportingDateId 411 412 413 414
CreatedDate Sep 5 201 Sep 5 201 Sep 5 201 Sep 5 201
Thanks tons for the answer!
You'll need to UNPIVOT all those columns first, then convert your Weeks into new columns. But in order to UNPIVOT the data, you'll have to convert all of the data types to be the same.
Since you are using SQL Server 2008, you can use CROSS APPLY to unpivot. The basic syntax will be:
select
WeekOfTheMonth,
DataType,
Value
from yourtable
cross apply
(
select 'Tenant', Tenant union all
select 'ReportingDate', convert(varchar(10), ReportingDate, 120) union all
select 'TotalEmployeesPerBranch', cast(TotalEmployeesPerBranch as varchar(10)) union all
select 'TotalOpenCount', cast(TotalOpenCount as varchar(10)) union all
select 'TotalClosedCount', cast(TotalClosedCount as varchar(10)) union all
select 'OpenCount_TitleAndEscrow', cast(OpenCount_TitleAndEscrow as varchar(10)) union all
select 'ClosedCount_TitleAndEscrow', cast(ClosedCount_TitleAndEscrow as varchar(10)) union all
select 'OpenCount_EscrowOnly', cast(OpenCount_EscrowOnly as varchar(10)) union all
select 'ClosedCount_EscrowOnly', cast(ClosedCount_EscrowOnly as varchar(10)) union all
select 'OpenCount_PreListingTask', cast(OpenCount_PreListingTask as varchar(10))
--- union all more columns
) c (DataType, value);
See SQL Fiddle with Demo. Then you'd apply the PIVOT to your Weeks:
select DataType,
Week1 = [1],
Week2 = [2],
Week3 = [3],
Week4 = [4]
from
(
select
WeekOfTheMonth,
DataType,
Value,
so,
seq = row_number() over(partition by WeekOfTheMonth order by wwnId)
from yourtable
cross apply
(
select 'Tenant', Tenant, 1 union all
select 'ReportingDate', convert(varchar(10), ReportingDate, 120), 2 union all
select 'TotalEmployeesPerBranch', cast(TotalEmployeesPerBranch as varchar(10)), 3 union all
select 'TotalOpenCount', cast(TotalOpenCount as varchar(10)), 4 union all
select 'TotalClosedCount', cast(TotalClosedCount as varchar(10)), 5 union all
select 'OpenCount_TitleAndEscrow', cast(OpenCount_TitleAndEscrow as varchar(10)), 6 union all
select 'ClosedCount_TitleAndEscrow', cast(ClosedCount_TitleAndEscrow as varchar(10)), 7 union all
select 'OpenCount_EscrowOnly', cast(OpenCount_EscrowOnly as varchar(10)),8 union all
select 'ClosedCount_EscrowOnly', cast(ClosedCount_EscrowOnly as varchar(10)), 9 union all
select 'OpenCount_PreListingTask', cast(OpenCount_PreListingTask as varchar(10)), 10
) c (DataType, value, so)
) d
pivot
(
max(value)
for WeekOfTheMonth in ([1], [2], [3], [4])
)p
order by seq, so
See SQL Fiddle with Demo.
Or you can use an aggregate function to create the new columns:
select Datatype,
max(case when WeekOfTheMonth = 1 then value else '0' end) Week1,
max(case when WeekOfTheMonth = 2 then value else '0' end) Week2,
max(case when WeekOfTheMonth = 3 then value else '0' end) Week3,
max(case when WeekOfTheMonth = 4 then value else '0' end) Week4
from
(
select
WeekOfTheMonth,
DataType,
Value,
so,
seq = row_number() over(partition by WeekOfTheMonth order by wwnId)
from yourtable
cross apply
(
select 'Tenant', Tenant, 1 union all
select 'ReportingDate', convert(varchar(10), ReportingDate, 120), 2 union all
select 'TotalEmployeesPerBranch', cast(TotalEmployeesPerBranch as varchar(10)), 3 union all
select 'TotalOpenCount', cast(TotalOpenCount as varchar(10)), 4 union all
select 'TotalClosedCount', cast(TotalClosedCount as varchar(10)), 5 union all
select 'OpenCount_TitleAndEscrow', cast(OpenCount_TitleAndEscrow as varchar(10)), 6 union all
select 'ClosedCount_TitleAndEscrow', cast(ClosedCount_TitleAndEscrow as varchar(10)), 7 union all
select 'OpenCount_EscrowOnly', cast(OpenCount_EscrowOnly as varchar(10)),8 union all
select 'ClosedCount_EscrowOnly', cast(ClosedCount_EscrowOnly as varchar(10)), 9 union all
select 'OpenCount_PreListingTask', cast(OpenCount_PreListingTask as varchar(10)), 10
) c (DataType, value, so)
) d
group by datatype, seq, so
order by seq, so
See SQL Fiddle with Demo

Calculate wrong amount in query

I have a table with some records now want to repeat this table content with some logic. I have two date start date and termination date, means record start from start_date and end on termination date, it will working fine but problem is calculate amount on it,
Logic is amount calculation formula
basesalary / 12 * ( SUTARate / 100 ) * ( x.num+1)
if this amount is less than SUTAMaximumAmount this amount is used, else 0. And one more thing if amount will be remain and year is complete then restart calculation from next year.. x.num is temporary table which hold 90 number from 1 to 90
Table
BaseSalary| S_Date | T_Date | SUTARate| SUTAMaximumAmount |A_S_Percent
48000 | 7-1-2013 | 3-15-2015 | 1.1 | 300 | 5
My result is
DAte amount
2013-07-01 00:00:00.000 44
2013-08-01 00:00:00.000 44
2013-09-01 00:00:00.000 44
2013-10-01 00:00:00.000 44
2013-11-01 00:00:00.000 44
2013-12-01 00:00:00.000 44
2014-01-01 00:00:00.000 36
2014-02-01 00:00:00.000 -8
2014-03-01 00:00:00.000 -52
2014-04-01 00:00:00.000 -96
2014-05-01 00:00:00.000 -140
2014-06-01 00:00:00.000 -184
2014-07-01 00:00:00.000 -228
2014-08-01 00:00:00.000 -272
2014-09-01 00:00:00.000 -316
2014-10-01 00:00:00.000 -360
2014-11-01 00:00:00.000 -404
2014-12-01 00:00:00.000 -448
2015-01-01 00:00:00.000 -492
2015-02-01 00:00:00.000 -536
2015-03-01 00:00:00.000 -580
and I want result like this
Date | Amount
7-1-2013 44
8-1-2013 44
9-1-2013 44
10-1-2013 44
11-1-2013 44
12-1-2013 44
1-1-2014 44
2-1-2014 44
3-1-2014 44
4-1-2014 44
5-1-2014 44
6-1-2014 44
7-1-2014 36
1-1-2015 44
2-1-2015 44
3-1-2015 44
Query
SELECT dateadd(M, (x.num),d.StartDate) AS TheDate,
Round( case when ((convert(float,d.SUTARate)/100* convert(integer,d.BaseSalary) / 12)*(x.num+1)) <=CONVERT(money,d.SUTAMaximumAmount)
then (convert(float,d.SUTARate)/100* convert(integer,d.BaseSalary)* / 12)
else (CONVERT(money,d.SUTAMaximumAmount)-((convert(float,d.SUTARate)/100* (convert(integer,d.BaseSalary) / 12)*x.num)))*Power((1+convert(float,d.AnnualSalaryIncreasePercent)/100),Convert(int,x.num/12)) end, 2) AS Amount,
FROM #Table AS x, myTbl AS d
WHERE (x.num >= 0) AND (x.num <= (DateDiff(M, d.StartDate, d.TerminationDate)) )
temporary table
create TABLE #Table (
num int NOT NULL,
);
;WITH Nbrs ( n ) AS (
SELECT 0 UNION ALL
SELECT 1 + n FROM Nbrs WHERE n < 99 )
INSERT #Table(num)
SELECT n FROM Nbrs
OPTION ( MAXRECURSION 99 )
this table used as x in above query
I created this SQLFiddle.
-- Numbers table is probably a good idea
WITH Nbrs ( num ) AS
(
SELECT 0 UNION ALL
SELECT 1 + num FROM Nbrs WHERE num < 99
)
-- All columns, except for 'num' come from myTbl
SELECT dateadd(M, (num),S_Date) AS TheDate,
Round(
CASE
WHEN (SUTARate / 100) * (BaseSalary / 12) <= SUTAMaximumAmount
THEN (SUTARate / 100) * (BaseSalary / 12)
ELSE 0
END
, 2) As Amount
-- This may be the number you were trying to multiply
,DatePart(Month, dateadd(M, (num),S_Date)) As PotentialMultiiplier
FROM Nbrs AS x, myTbl AS d
WHERE (num >= 0)
AND (num <= (DateDiff(M, S_Date, T_Date)) )
I am not entirely sure what your goal is, but you are probably on the right track with a numbers table. Because the result you are going for does not change much over time (i.e., nearly every month has an amount of $44), it is difficult to determine the correct code for the query. So, I recommend you provide a different set of data for better result-checking.
If you fiddle with the SQL in the provided link, you can re-post with better code, and then we can better solve your issue.