Sorting query output by Month name - sql-server

I am trying to extract values from Excel using an SQL Query, but what I've been struggling with is sorting the months in their respective order. Right now the table is being sorted A-Z, I tried playing around with DATEPART, but was not very successful as I was getting an Int16 error.
Select F1,
SUM(F2),
ROUND(SUM(REPLACE(F3, ',', '.')), 2),
ROUND(SUM(REPLACE(F4, ',', '.')), 2)
FROM [Sheet1$]
WHERE F1 IN ('January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December')
GROUP BY F1;
This is the query that works, but the result is:
I am also open to any suggestions that could improve my query speed as the document is quite big, about 50k rows, thanks.
For anyone wondering the final query that worked was:
Select F1,
SUM(F2),
ROUND(SUM(REPLACE(F3, ',', '.')), 2),
ROUND(SUM(REPLACE(F4, ',', '.')), 2)
FROM [Sheet1$]
WHERE F1 IN ('January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December')
GROUP BY F1
ORDER BY SWITCH(
F1='January', 1,
F1='February', 2,
F1='March', 3,
F1='April', 4,
F1='May', 5,
F1='June', 6,
F1='July', 7,
F1='August', 8,
F1='September', 9,
F1='October', 10,
F1='November', 11,
F1='December', 12
);

Either use a CASE expression:
Select
f1,
SUM(f2),
ROUND(SUM(REPLACE(f3, ',', '.')), 2),
ROUND(SUM(REPLACE(f4, ',', '.')), 2)
FROM [Sheet1$]
WHERE F1 IN ('January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December')
GROUP BY F1
ORDER BY
CASE F1
WHEN 'January' THEN 1
WHEN 'February' THEN 2
WHEN 'March' THEN 3
WHEN 'April' THEN 4
WHEN 'May' THEN 5
WHEN 'June' THEN 6
WHEN 'July' THEN 7
WHEN 'August' THEN 8
WHEN 'September' THEN 9
WHEN 'October' THEN 10
WHEN 'November' THEN 111
WHEN 'December' THEN 12
END;
Or create a month table on the fly:
Select
s.f1,
SUM(s.f2),
ROUND(SUM(REPLACE(s.f3, ',', '.')), 2),
ROUND(SUM(REPLACE(s.f4, ',', '.')), 2)
FROM [Sheet1$] s
JOIN VALUES
(
('January', 1),
('February', 2),
('March', 3),
('April', 4),
('May', 5),
('June', 6),
('July', 7),
('August', 8),
('September', 9),
('October', 10),
('November', 11),
('December', 12)
) months(month_name, month_number) ON s.f1 = months.month_name
GROUP BY s.f1
ORDER BY months.month_number;
Or create a real month table.

You could do:
order by datepart(mm, f1 + ' 1 2000')

Related

Window based averages based on ranges within another table

I have a table that has positions like so:
create or replace table data (
pos int not null,
val float not null,
constraint data_pk primary key (pos)
);
And, a ranges type table like so:
create or replace table ranges (
label varchar(32) not null,
left int not null,
right int not null,
constraint ranges_pk primary key (label)
);
with ranges like
('alpha', 11, 13),
('bravo', 11, 14),
('charlie', 11, 15),
('echo', 12, 18),
('delta', 12, 19),
('foxtrot', 13, 20)
for each label, I need to lookup every possible 3 subrange within the "data" table, take these 3 subrange averages, and then average them...
I couldn't think of a good way to describe what I'm after, so I thought I'd show what I'd expect for 'charlie':
The results for charlie in the select should be:
('charlie', 40.111), -- avg(avg(data[pos=11], data[pos=12], data[pos=13]), avg(data[pos=12], data[pos=13], data[pos=14]), avg(data[pos=13], data[pos=14], data[pos=15]))
-- -> avg(avg(31, 37, 41), avg(37, 41, 43), avg(41, 43, 47))
-- -> avg(36.333, 40.333, 43.667) -> 40.111
(for data like)
insert into data (pos, val) values
(1, 2), (2, 3), (3, 5), (4, 7), (5, 11), (6, 13), (7, 17), (8, 19),
(9, 23), (10, 29), (11, 31), (12, 37), (13, 41), (14, 43), (15, 47), (16, 53),
(17, 59), (18, 61), (19, 67), (20, 71), (21, 73), (22, 79), (23, 83), (24, 89),
(25, 97), (26, 101), (27, 103), (28, 107), (29, 109), (30, 113), (31, 127), (32, 131),
(33, 137), (34, 139), (35, 149), (36, 151), (37, 157), (38, 163), (39, 167), (40, 173),
(41, 179), (42, 181), (43, 191), (44, 193), (45, 197), (46, 199), (47, 211), (48, 223),
(49, 227), (50, 229), (51, 233), (52, 239), (53, 241), (54, 251);
Is there a way to do this within Snowflake SQL? Or must I resort to python to do this? If it helps I made a gist with more data..
Thanks!
Is there a way to do this within Snowflake SQL? Or must I resort to python to do this?
SQL language is expressive enough to handle such case.
Key point here is to use windowed average with windows size of 3 and then average moving averages:
WITH cte AS (
SELECT r.label, r.left, r.right, d.val,
AVG(d.val) OVER(PARTITION BY r.label ORDER BY d.pos ROWS
BETWEEN 2 PRECEDING AND CURRENT ROW) AS r
FROM ranges r
JOIN data d
ON d.pos BETWEEN r.left AND r.right
QUALIFY ROW_NUMBER() OVER(PARTITION BY r.label ORDER BY d.pos) > 2
)
SELECT label, AVG(r) AS output
FROM cte
GROUP BY label
ORDER BY label;
Output:
Intermediate step to ilustrate:
WITH cte AS (
SELECT r.label, r.left, r.right, d.val,
AVG(d.val) OVER(PARTITION BY r.label ORDER BY d.pos
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS r
FROM ranges r
JOIN data d
ON d.pos BETWEEN r.left AND r.right
QUALIFY ROW_NUMBER() OVER(PARTITION BY r.label ORDER BY d.pos) > 2
)
SELECT *
FROM cte
ORDER BY label, r;
Output:
Here is a step by step answer:
WITH data(pos, val) AS (
SELECT * FROM VALUES
(1, 2), (2, 3), (3, 5), (4, 7), (5, 11), (6, 13), (7, 17), (8, 19),
(9, 23), (10, 29), (11, 31), (12, 37), (13, 41), (14, 43), (15, 47), (16, 53),
(17, 59), (18, 61), (19, 67), (20, 71), (21, 73), (22, 79), (23, 83), (24, 89),
(25, 97), (26, 101), (27, 103), (28, 107), (29, 109), (30, 113), (31, 127), (32, 131),
(33, 137), (34, 139), (35, 149), (36, 151), (37, 157), (38, 163), (39, 167), (40, 173),
(41, 179), (42, 181), (43, 191), (44, 193), (45, 197), (46, 199), (47, 211), (48, 223),
(49, 227), (50, 229), (51, 233), (52, 239), (53, 241), (54, 251)
), codes(name,s_val, e_val) AS (
SELECT * FROM VALUES
('alpha', 11, 13),
('bravo', 11, 14),
('charlie', 11, 15),
('echo', 12, 18),
('delta', 12, 19),
('foxtrot', 13, 20)
), ranges as (
SELECT row_number() over (order by null)-1 as seq
FROM table(generator(rowcount => 200))
), boost_codes AS (
select c.name
,c.s_val + r.seq + 0 as b1
,c.s_val + r.seq + 2 as b3
from codes as c
join ranges as r
ON r.seq <= (e_val - s_val - 2)
), almost_there AS (
select
bc.name
,avg(d.val) as partial
from boost_codes as bc
join data as d ON d.pos between bc.b1 and bc.b3
GROUP BY 1, bc.b1
)
SELECT name
,round(avg(partial),3) as output
FROM almost_there
GROUP BY 1
ORDER BY 1;
which gives:
NAME
OUTPUT
alpha
36.333
bravo
38.333
charlie
40.111
delta
50.778
echo
48.467
foxtrot
55.111

SQL Query create two column each with different values from two table [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I Have to create two-column different value with the same data, important thing data is from combining two tables with the inner join Statement. Here are the table1 and table 2 (it's like attendance report)
Am attaching tables
Table 1
Create a table
\* table 1 *\
CREATE TABLE [dbo].[tsStudAttandance](
[IDNo] [int] IDENTITY(1,1) NOT NULL,
[StudentName] [varchar](300) NULL,
[TrainnerName] [varchar](100) NULL,
[Date] [date] NULL,
[InTime] [varchar](50) NOT NULL,
[Weekday] [varchar](50) NULL,
[OutTime] [varchar](50) NULL,
[StudListId] [int] NULL,
CONSTRAINT [PK_tsAttandance] PRIMARY KEY CLUSTERED
(
[IDNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
/* INSERT QUERY NO: 1 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
1, 'Ms.Eva', 'John', '8/12/2019', '9:00 AM', 'Monday', '1:00 PM', 1, 4.00, 1
);
/* INSERT QUERY NO: 2 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
2, 'Mr.Stev Job', 'John', '8/12/2019', '11:00 AM', 'Monday', '1:00 PM', 3, 2.00, 3
);
/* INSERT QUERY NO: 3 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
3, 'Mr.Bill Gate', 'John', '8/12/2019', '9:00 AM', 'Monday', '11:00 AM', 4, 2.00, 3
);
/* INSERT QUERY NO: 4 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
4, 'Mr.Krish', 'Stev', '8/12/2019', '9:00 AM', 'Monday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 5 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
5, 'Mr.Chisty', 'Stev', '8/12/2019', '5:00 PM', 'Monday', '7:00 PM', 6, 2.00, 3
);
/* INSERT QUERY NO: 6 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
6, 'Mr.Micky', 'Stev', '8/12/2019', '11:00 AM', 'Monday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 7 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
7, 'Ms.Victorya', 'John', '8/12/2019', '5:00 PM', 'Monday', '7:00 PM', 9, 2.00, 3
);
/* INSERT QUERY NO: 8 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
8, 'Ms.Sheena', 'Stev', '8/12/2019', '7:00 PM', 'Monday', '9:00 PM', 10, 2.00, 1
);
/* INSERT QUERY NO: 9 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
9, 'Mr.Krish', 'Stev', '8/13/2019', '9:00 AM', 'Tuesday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 10 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
10, 'Mr.Micky', 'Stev', '8/13/2019', '11:00 AM', 'Tuesday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 11 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
11, 'Mr.John Stev', 'Stev', '8/14/2019', '11:00 AM', 'Wednesday', '1:00 PM', 2, 2.00, 4
);
/* INSERT QUERY NO: 12 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
12, 'Mr.Stev Job', 'John', '8/14/2019', '11:00 AM', 'Wednesday', '1:00 PM', 3, 2.00, 3
);
/* INSERT QUERY NO: 13 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
13, 'Mr.Bill Gate', 'John', '8/14/2019', '9:00 AM', 'Wednesday', '11:00 AM', 4, 2.00, 3
);
/* INSERT QUERY NO: 14 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
14, 'Mr.Krish', 'Stev', '8/14/2019', '9:00 AM', 'Wednesday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 15 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
15, 'Mr.Chisty', 'Stev', '8/14/2019', '5:00 PM', 'Wednesday', '7:00 PM', 6, 2.00, 3
);
/* INSERT QUERY NO: 16 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
16, 'Mr.Vicky', 'John', '8/14/2019', '7:00 PM', 'Wednesday', '9:00 PM', 7, 2.00, 1
);
/* INSERT QUERY NO: 17 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
17, 'Mr.Micky', 'Stev', '8/14/2019', '11:00 AM', 'Wednesday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 18 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
18, 'Ms.Victorya', 'John', '8/14/2019', '5:00 PM', 'Wednesday', '7:00 PM', 9, 2.00, 3
);
/* INSERT QUERY NO: 19 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
19, 'Ms.Sheena', 'Stev', '8/14/2019', '7:00 PM', 'Wednesday', '9:00 PM', 10, 2.00, 1
);
/* INSERT QUERY NO: 20 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
20, 'Mr.Krish', 'Stev', '8/15/2019', '9:00 AM', 'Thursday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 21 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
21, 'Mr.Micky', 'Stev', '8/15/2019', '11:00 AM', 'Thursday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 22 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
22, 'Mr.John Stev', 'Stev', '8/17/2019', '11:00 AM', 'Saturday', '1:00 PM', 2, 2.00, 4
);
/* INSERT QUERY NO: 23 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
23, 'Mr.Krish', 'Stev', '8/17/2019', '9:00 AM', 'Saturday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 24 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
24, 'Mr.Micky', 'Stev', '8/17/2019', '11:00 AM', 'Saturday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 25 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
25, 'Mr.John Stev', 'Stev', '8/18/2019', '11:00 AM', 'Sunday', '1:00 PM', 2, 2.00, 4
);
/* INSERT QUERY NO: 26 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
26, 'Mr.Stev Job', 'John', '8/18/2019', '11:00 AM', 'Sunday', '1:00 PM', 3, 2.00, 3
);
/* INSERT QUERY NO: 27 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
27, 'Mr.Bill Gate', 'John', '8/18/2019', '9:00 AM', 'Sunday', '11:00 AM', 4, 2.00, 3
);
/* INSERT QUERY NO: 28 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
28, 'Mr.Krish', 'Stev', '8/18/2019', '9:00 AM', 'Sunday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 29 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
29, 'Mr.Chisty', 'Stev', '8/18/2019', '5:00 PM', 'Sunday', '7:00 PM', 6, 2.00, 3
);
/* INSERT QUERY NO: 30 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
30, 'Mr.Micky', 'Stev', '8/18/2019', '11:00 AM', 'Sunday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 31 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
31, 'Ms.Victorya', 'John', '8/18/2019', '5:00 PM', 'Sunday', '7:00 PM', 9, 2.00, 3
);
/* INSERT QUERY NO: 32 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
32, 'Ms.Eva', 'John', '8/19/2019', '9:00 AM', 'Monday', '1:00 PM', 1, 4.00, 1
);
/* INSERT QUERY NO: 33 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
33, 'Mr.John Stev', 'Stev', '8/19/2019', '11:00 AM', 'Monday', '1:00 PM', 2, 2.00, 4
);
/* INSERT QUERY NO: 34 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
34, 'Mr.Stev Job', 'John', '8/19/2019', '11:00 AM', 'Monday', '1:00 PM', 3, 2.00, 3
);
/* INSERT QUERY NO: 35 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
35, 'Mr.Bill Gate', 'John', '8/19/2019', '9:00 AM', 'Monday', '11:00 AM', 4, 2.00, 3
);
/* INSERT QUERY NO: 36 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
36, 'Mr.Krish', 'Stev', '8/19/2019', '9:00 AM', 'Monday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 37 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
37, 'Mr.Chisty', 'Stev', '8/19/2019', '5:00 PM', 'Monday', '7:00 PM', 6, 2.00, 3
);
/* INSERT QUERY NO: 38 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
38, 'Mr.Micky', 'Stev', '8/19/2019', '11:00 AM', 'Monday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 39 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
39, 'Ms.Victorya', 'John', '8/19/2019', '5:00 PM', 'Monday', '7:00 PM', 9, 2.00, 3
);
/* INSERT QUERY NO: 40 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
40, 'Ms.Sheena', 'Stev', '8/19/2019', '7:00 PM', 'Monday', '9:00 PM', 10, 2.00, 1
);
/* INSERT QUERY NO: 41 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
41, 'Mr.John Stev', 'Stev', '8/20/2019', '11:00 AM', 'Tuesday', '1:00 PM', 2, 2.00, 4
);
/* INSERT QUERY NO: 42 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
42, 'Mr.Krish', 'Stev', '8/20/2019', '9:00 AM', 'Tuesday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 43 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
43, 'Mr.Micky', 'Stev', '8/20/2019', '11:00 AM', 'Tuesday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 44 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
44, 'Mr.John Stev', 'Stev', '8/21/2019', '11:00 AM', 'Wednesday', '1:00 PM', 2, 2.00, 4
);
/* INSERT QUERY NO: 45 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
45, 'Mr.Stev Job', 'John', '8/21/2019', '11:00 AM', 'Wednesday', '1:00 PM', 3, 2.00, 3
);
/* INSERT QUERY NO: 46 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
46, 'Mr.Bill Gate', 'John', '8/21/2019', '9:00 AM', 'Wednesday', '11:00 AM', 4, 2.00, 3
);
/* INSERT QUERY NO: 47 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
47, 'Mr.Krish', 'Stev', '8/21/2019', '9:00 AM', 'Wednesday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 48 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
48, 'Mr.Chisty', 'Stev', '8/21/2019', '5:00 PM', 'Wednesday', '7:00 PM', 6, 2.00, 3
);
/* INSERT QUERY NO: 49 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
49, 'Mr.Vicky', 'John', '8/21/2019', '7:00 PM', 'Wednesday', '9:00 PM', 7, 2.00, 1
);
/* INSERT QUERY NO: 50 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
50, 'Mr.Micky', 'Stev', '8/21/2019', '11:00 AM', 'Wednesday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 51 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
51, 'Ms.Victorya', 'John', '8/21/2019', '5:00 PM', 'Wednesday', '7:00 PM', 9, 2.00, 3
);
/* INSERT QUERY NO: 52 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
52, 'Ms.Sheena', 'Stev', '8/21/2019', '7:00 PM', 'Wednesday', '9:00 PM', 10, 2.00, 1
);
/* INSERT QUERY NO: 53 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
53, 'Mr.Krish', 'Stev', '8/22/2019', '9:00 AM', 'Thursday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 54 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
54, 'Mr.Micky', 'Stev', '8/22/2019', '11:00 AM', 'Thursday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 55 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
55, 'Mr.John Stev', 'Stev', '8/24/2019', '11:00 AM', 'Saturday', '1:00 PM', 2, 2.00, 4
);
/* INSERT QUERY NO: 56 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
56, 'Mr.Krish', 'Stev', '8/24/2019', '9:00 AM', 'Saturday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 57 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
57, 'Mr.Micky', 'Stev', '8/24/2019', '11:00 AM', 'Saturday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 58 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
58, 'Mr.John Stev', 'Stev', '8/25/2019', '11:00 AM', 'Sunday', '1:00 PM', 2, 2.00, 4
);
/* INSERT QUERY NO: 59 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
59, 'Mr.Stev Job', 'John', '8/25/2019', '11:00 AM', 'Sunday', '1:00 PM', 3, 2.00, 3
);
/* INSERT QUERY NO: 60 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
60, 'Mr.Bill Gate', 'John', '8/25/2019', '9:00 AM', 'Sunday', '11:00 AM', 4, 2.00, 3
);
/* INSERT QUERY NO: 61 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
61, 'Mr.Krish', 'Stev', '8/25/2019', '9:00 AM', 'Sunday', '11:00 AM', 5, 2.00, 6
);
/* INSERT QUERY NO: 62 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
62, 'Mr.Chisty', 'Stev', '8/25/2019', '5:00 PM', 'Sunday', '7:00 PM', 6, 2.00, 3
);
/* INSERT QUERY NO: 63 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
63, 'Mr.Micky', 'Stev', '8/25/2019', '11:00 AM', 'Sunday', '1:00 PM', 8, 2.00, 6
);
/* INSERT QUERY NO: 64 */
INSERT INTO table_name(IDNo, StudentName, TrainnerName, Date, InTime, Weekday, OutTime, StudListId, Hours, DAYS)
VALUES
(
64, 'Ms.Victorya', 'John', '8/25/2019', '5:00 PM', 'Sunday', '7:00 PM', 9, 2.00, 3
);
Table 2
\* Table 2 *\
CREATE TABLE [dbo].[tsStudenList](
[IdNo] [int] IDENTITY(1,1) NOT NULL,
[StudentName] [varchar](300) NULL,
[TrainnerName] [varchar](300) NULL,
[StudentRegNo] [varchar](15) NULL,
[Course] [varchar](max) NULL,
[Duration] [smallint] NULL,
[Schedule] [varchar](100) NULL,
[Days] [int] NULL,
[StartDate] AS (CONVERT([date],getdate())),
[Timing] [varchar](100) NULL,
CONSTRAINT [PK_tsStudenList] PRIMARY KEY CLUSTERED
(
[IdNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[tsStudAttandance] WITH CHECK ADD CONSTRAINT [FK_tsStudAttandance_tsStudenList] FOREIGN KEY([StudListId])
REFERENCES [dbo].[tsStudenList] ([IdNo])
GO
ALTER TABLE [dbo].[tsStudAttandance] CHECK CONSTRAINT [FK_tsStudAttandance_tsStudenList]
GO
/* INSERT QUERY NO: 1 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
1, 'Ms.Eva', 'John', 'TSSR1900001', 'CCNA', 60, 'SAT', 1, '8/12/2019', '09:00 AM - 01:00 PM'
);
/* INSERT QUERY NO: 2 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
2, 'Mr.John Stev', 'Stev', 'TSSR1900002', 'CCNA', 60, 'SAT-WED', 4, '8/12/2019', '09:00 AM - 01:00 PM'
);
/* INSERT QUERY NO: 3 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
3, 'Mr.Stev Job', 'John', 'TSSR1900003', 'CCNP', 70, 'SUN-MON-WED', 3, '8/12/2019', '09:00 AM - 11 :00 AM'
);
/* INSERT QUERY NO: 4 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
4, 'Mr.Bill Gate', 'John', 'TSSR1900004', 'PHOTOSHOP', 20, 'SUN-MON-WED', 3, '8/12/2019', '09:00 AM - 11:00 AM'
);
/* INSERT QUERY NO: 5 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
5, 'Mr.Krish', 'Stev', 'TSSR1900005', 'INDESIGN', 24, 'SAT-THR', 6, '8/12/2019', '09:00 AM - 01:00 PM'
);
/* INSERT QUERY NO: 6 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
6, 'Mr.Chisty', 'Stev', 'TSSR1900006', 'CEH', 80, 'SUN-MON-WED', 3, '8/12/2019', '11:00 AM - 01:00 PM'
);
/* INSERT QUERY NO: 7 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
7, 'Mr.Vicky', 'John', 'TSSR1900007', 'CEH', 80, 'WED', 1, '8/12/2019', '05:00 PM - 07:00 PM'
);
/* INSERT QUERY NO: 8 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
8, 'Mr.Micky', 'Stev', 'TSSR1900008', 'INDESIGN', 24, 'SAT-THR', 6, '8/12/2019', '09:00 AM - 01:00 PM'
);
/* INSERT QUERY NO: 9 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
9, 'Ms.Victorya', 'John', 'TSSR1900009', 'PHOTOSHOP', 24, 'SUN-MON-WED', 3, '8/12/2019', '09:00 AM - 11:00 PM'
);
/* INSERT QUERY NO: 10 */
INSERT INTO table_name(idno, studentname, trainnername, studentregno, course, duration, schedule, days, startdate, timing)
VALUES
(
10, 'Ms.Sheena', 'Stev', 'TSSR1900010', 'CEH', 40, 'MON & WED', 2, '8/12/2019', '07:00 PM - 09:00 PM'
);
Need a Final Report like this
Here is the Remark should come to YES or No by comparing they Intime and OutTime (By checking the Schedule if SAT-MON-WED means three days, so if the hours are less then 6 Remark Should 'NO'. Like That Should Check Schedule and Time for Remarks) and Percentage of class status Should sum the hours of this week(Sat-Thu) and divide by Duration of the second table. I got That result Week But I need overall status too if I use Where Clauses Between 'Start Date' And 'End Date'.
Here the sample report for YES ON and Discontinued(more than one month is optional)
This possibility should be when a student does not attend the class for one month Discontinued and in 6days class attended less than or equal to 3 No
Most Important Overall Status and Current week Status as the above pic
Here is the Code Which I tried
BEGIN
SELECT tsStudAttandance.StudentName as 'Name', tsStudenList.StartDate as 'Start Date',
CASE WHEN
sum(
case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float)) = CAST(tsStudenList.Duration as float)
Then (SELECT top 1 tsStudAttandance.Date FROM tsStudAttandance ORDER BY tsStudAttandance.Date DESC)
END as 'End Date',
cast(cast(round(sum(
case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float))
/ cast(tsStudenList.Duration as float)*100,2) AS DECIMAL(18,2)) as varchar(100)) + ' %' as 'Class Status in %',
(
cast(cast(round(sum(
case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float))
/ cast(tsStudenList.Duration as float)*100,2) AS DECIMAL(18,2)) as varchar(100)) + ' %' ) as 'Over Class Status in %',
tsStudenList.Course as 'Course Name', tsStudenList.Timing, tsStudenList.Schedule
FROM tsStudAttandance INNER JOIN dbo.tsStudenList ON tsStudAttandance.StudListId = tsStudenList.IdNo
GROUP BY tsStudAttandance.StudentName,tsStudenList.Duration, tsStudenList.StartDate, tsStudenList.Schedule, tsStudenList.Course, tsStudenList.Timing, tsStudenList.Schedule
End;
Here the Code for the above Question
Use modeldb
Go
BEGIN
Select a.[SNo],a.Name, a.[StartDate],b.[EndDate], a.[WeekStatus], b.[OverAllStatus],a.[CourseName], a.Timing, a.Schedule, a.Regular FROM
(SELECT
ROW_NUMBER() OVER(ORDER BY tsStudAttandance.StudentName ASC) as 'SNo',
tsStudAttandance.StudentName as 'Name', tsStudenList.StartDate as 'StartDate',tsStudenList.StudentRegNo as 'RegNo',
cast(cast(round(sum(
case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float))
/ cast(tsStudenList.Duration as float)*100,2) AS DECIMAL(18,2)) as varchar(100)) + ' %' as 'WeekStatus',
tsStudenList.Course as 'CourseName', tsStudenList.Timing, tsStudenList.Schedule,
(Case
When tsStudenList.InDays = 6
AND ((sum(case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float)))/2)>=3
Then
'YES'
When tsStudenList.InDays = 5
AND ((sum(case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float)))/2)>=2
Then
'YES'
When tsStudenList.InDays = 4
AND ((sum(case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float)))/2)>=1
Then
'YES'
When tsStudenList.InDays = 3
AND ((sum(case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float)))/2)>=1
Then
'YES'
When tsStudenList.InDays = 2
AND ((sum(case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float)))/2)>=1
Then
'YES'
When tsStudenList.InDays = 1
AND ((sum(case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float)))/2)>=1
Then
'YES'
ELSE
'No'
End)
As 'Regular'
FROM tsStudAttandance INNER JOIN dbo.tsStudenList ON tsStudAttandance.StudListId = tsStudenList.IdNo Where tsStudAttandance.Date Between '2019-08-12' AND '2019-08-17' GROUP BY tsStudAttandance.StudentName,tsStudenList.Duration, tsStudenList.StartDate, tsStudenList.Schedule, tsStudenList.Course, tsStudenList.Timing, tsStudenList.Schedule, tsStudenList.InDays,tsStudenList.StudentRegNo) a
Left join (SELECT tsStudAttandance.StudentName as 'Name' ,
CASE WHEN
sum(
case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime ,2)))as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime,2)))as float)) = CAST(tsStudenList.Duration as float)
Then (SELECT top 1 tsStudAttandance.Date FROM tsStudAttandance ORDER BY tsStudAttandance.Date DESC)
END as 'EndDate',
(cast(cast(round(sum(
case
when CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.OutTime , 2))) = 'PM' AND CONVERT(VARCHAR(6), TRIM(' ' FROM Right(tsStudAttandance.InTime , 2))) ='AM'
then cast(CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)+12
else cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float)
end
- cast(CONVERT(VARCHAR(6), TRIM(':00 AM' FROM LEFT(tsStudAttandance.Intime , 2)) ) as float))
/ cast(tsStudenList.Duration as float)*100,2) AS DECIMAL(18,2)) as varchar(100)) + ' %' ) as 'OverAllStatus'
From tsStudAttandance INNER JOIN dbo.tsStudenList ON tsStudAttandance.StudListId = tsStudenList.IdNo Group by tsStudAttandance.StudentName,tsStudenList.Duration) b on a.Name = b.Name
END;
The above Question records limited to two weeks so if for Month and more then a month We can adjust Case for Discontinued in Regular Remark Part.
Answer 1 is Case to Create Stored Procedure Run Good In SQL, Instead of
CONVERT We can USE SUBSTRING
CONVERT(VARCHAR(6), TRIM(':00 PM' FROM LEFT(tsStudAttandance.OutTime , 2)) ) as float) Can be Changed to SUBSTRING(tsStudAttandance.OutTime,1,2) and By Using SUBSTRING O9 Will Be Consider as 9 SO we Can USE Replace() and LEN()
Here is the code that
BEGIN
Select a.Name, a.[StartDate],b.[EndDate], a.[WeekStatus], b.[OverAllStatus],a.[CourseName], a.Timing, a.Schedule, a.Regular FROM
(SELECT
tsStudAttandance.StudentName as 'Name', tsStudenList.StartDate as 'StartDate',tsStudenList.StudentRegNo as 'RegNo',
cast(cast(round(sum(
case
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='AM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)+12
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='PM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
else
cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
end
- cast(REPLACE(SUBSTRING(tsStudAttandance.InTime,1,2),':','') as int)
)
/ cast(tsStudenList.Duration as float)*100,2) AS DECIMAL(18,2)) as varchar(100)) + ' %' as 'WeekStatus',
tsStudenList.Course as 'CourseName', tsStudenList.Timing, tsStudenList.Schedule,
(Case
When tsStudenList.InDays = 6
AND ((sum(case
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='AM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)+12
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='PM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
else
cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
end
- cast(REPLACE(SUBSTRING(tsStudAttandance.InTime,1,2),':','') as int)))/2)>=3
Then
'YES'
When tsStudenList.InDays = 5
AND ((sum(case
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='AM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)+12
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='PM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
else
cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
end
- cast(REPLACE(SUBSTRING(tsStudAttandance.InTime,1,2),':','') as int)))/2)>=2
Then
'YES'
When tsStudenList.InDays = 4
AND ((sum(case
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='AM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)+12
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='PM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
else
cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
end
- cast(REPLACE(SUBSTRING(tsStudAttandance.InTime,1,2),':','') as int)))/2)>=1
Then
'YES'
When tsStudenList.InDays = 3
AND ((sum(case
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='AM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)+12
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='PM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
else
cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
end
- cast(REPLACE(SUBSTRING(tsStudAttandance.InTime,1,2),':','') as int)))/2)>=1
Then
'YES'
When tsStudenList.InDays = 2
AND ((sum(case
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='AM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)+12
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='PM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
else
cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
end
- cast(REPLACE(SUBSTRING(tsStudAttandance.InTime,1,2),':','') as int)))/2)>=1
Then
'YES'
When tsStudenList.InDays = 1
AND ((sum(case
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='AM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)+12
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='PM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
else
cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
end
- cast(REPLACE(SUBSTRING(tsStudAttandance.InTime,1,2),':','') as int)))/2)>=1
Then
'YES'
ELSE
'No'
End)
As 'Regular'
FROM tsStudAttandance INNER JOIN dbo.tsStudenList ON tsStudAttandance.StudListId = tsStudenList.IdNo Where tsStudAttandance.Date Between '2019-08-12' AND '2019-08-17' GROUP BY tsStudAttandance.StudentName,tsStudenList.Duration, tsStudenList.StartDate, tsStudenList.Schedule, tsStudenList.Course, tsStudenList.Timing, tsStudenList.Schedule, tsStudenList.InDays,tsStudenList.StudentRegNo) a
Left join (SELECT tsStudAttandance.StudentName as 'Name' ,
CASE WHEN
sum(case
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='AM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)+12
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='PM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
else
cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
end
- cast(REPLACE(SUBSTRING(tsStudAttandance.InTime,1,2),':','') as int)) = CAST(tsStudenList.Duration as Int)
Then (SELECT top 1 tsStudAttandance.Date FROM tsStudAttandance ORDER BY tsStudAttandance.Date DESC)
END as 'EndDate',
(cast(cast(round(sum(
(case
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='AM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)+12
when SUBSTRING(tsStudAttandance.OutTime,len(RTRIM(tsStudAttandance.OutTime))-1,len(RTRIM(tsStudAttandance.OutTime))) = 'PM' AND SUBSTRING(tsStudAttandance.InTime,len(RTRIM(tsStudAttandance.InTime))-1,len(RTRIM(tsStudAttandance.InTime))) ='PM'
then cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
else
cast(REPLACE(SUBSTRING(tsStudAttandance.OutTime,1,2),':','') as int)
end
- cast(REPLACE(SUBSTRING(tsStudAttandance.InTime,1,2),':','') as int)))
/ cast(tsStudenList.Duration as float)*100,2) AS DECIMAL(18,2)) as varchar(100)) + ' %' ) as 'OverAllStatus'
From tsStudAttandance INNER JOIN dbo.tsStudenList ON tsStudAttandance.StudListId = tsStudenList.IdNo Group by tsStudAttandance.StudentName,tsStudenList.Duration) b on a.Name = b.Name
End;

Select distinct in week and distinct overall per week

I have an example on sql fiddle. What I am trying to do is divide the overall COUNT(DISTINCT ID) by the weekly COUNT(DISTINCT ID). For example if I have the following conceptual setup of what the result should be.
year week id_set overall_distinct week_distinct result
2016 1 A,A,A,B,B,C 0 3 0
2016 2 A,B,C,C,D 1 4 .25
2016 3 A,B,C,E,F 2 5 .4
The table linked to on sql fiddle has the following schema. Also, in reality I do have multiple values for 'year'.
CREATE TABLE all_ids
([year] int, [week] int, [id] varchar(57))
;
INSERT INTO all_ids
([year], [week], [id])
VALUES
(2016, 1, 'A'),
(2016, 1, 'A'),
(2016, 1, 'A'),
(2016, 1, 'B'),
(2016, 1, 'B'),
(2016, 1, 'C'),
(2016, 2, 'A'),
(2016, 2, 'B'),
(2016, 2, 'C'),
(2016, 2, 'C'),
(2016, 2, 'D'),
(2016, 3, 'A'),
(2016, 3, 'B'),
(2016, 3, 'C'),
(2016, 3, 'E'),
(2016, 3, 'F')
;
Edit
I apologize for the confusion. The above table was just a conceptual example of the result. The actual result only needs to look like the following.
year week overall_distinct week_distinct result
2016 1 0 3 0
2016 2 1 4 .25
2016 3 2 5 .4
there is no need to include id_set
I used dense_rank and max() over () to simulate count (distinct ...) with window functions. You could try to do it with another subquery
select
year, week
, id_set = stuff((
select
',' + a.id
from
all_ids a
where
a.year = t.year
and a.week = t.week
order by a.id
for xml path('')
), 1, 1, '')
, overall_distinct = count(case when cnt = 1 then 1 end)
, week_distinct = count(distinct id)
, result = cast(count(case when cnt = 1 then 1 end) * 1.0 / count(distinct id) as decimal(10, 2))
from (
select
year, week, id, cnt = max(dr) over (partition by id)
from (
select
*, dr = dense_rank() over (partition by id order by year, week)
From
all_ids
) t
) t
group by year, week
Output
year week id_set overall_distinct week_distinct result
--------------------------------------------------------------------------
2016 1 A,A,A,B,B,C 0 3 0.00
2016 2 A,B,C,C,D 1 4 0.25
2016 3 A,B,C,E,F 2 5 0.40
This would be one way, probably not the best one:
;with weekly as
(
select year, week, count(distinct id) nr
from all_ids
group by year, week
),
overall as
(
select a.week, count(distinct a.id) nr
from all_ids a
where a.id not in (select id from all_ids where week <> a.week and id = a.id )
group by week
)
select distinct a.year
, a.week
, stuff((select ', ' + id
from all_ids
where year = a.year and week = a.week
for xml path('')), 1, 1, '') ids
, w.Nr weeklyDistinct
, isnull(t.Nr, 0) overallDistinct
from all_ids a join weekly w on a.year = w.year and a.week = w.week
left join overall t on t.week = a.week
One statement count only
declare #t table (y int, w int, id varchar(57));
INSERT #t (y, w, id)
VALUES
(2016, 1, 'A'),
(2016, 1, 'A'),
(2016, 1, 'A'),
(2016, 1, 'B'),
(2016, 1, 'B'),
(2016, 1, 'C'),
(2016, 2, 'A'),
(2016, 2, 'B'),
(2016, 2, 'C'),
(2016, 2, 'C'),
(2016, 2, 'D'),
(2016, 3, 'A'),
(2016, 3, 'B'),
(2016, 3, 'C'),
(2016, 3, 'E'),
(2016, 3, 'F');
select t1.w, count(distinct t1.id) as wk
, (count(distinct t1.id) - count(distinct t2.id)) as [all]
, (cast(1 as smallmoney) - cast(count(distinct t2.id) as smallmoney) / count(distinct t1.id)) as [frac]
from #t t1
left join #t t2
on t2.id = t1.id
and t2.w <> t1.w
group by t1.w
order by t1.w;

distribution of income over time based on rule set

Not sure if I was able to properly describe the title of my question but I haven't done anything this complex in T-Sql. Here's what I'm trying to achieve.
After several queries and table building, I got the data (below) in a temp table which probably will become a permanent table.
The part I need help with is, Need to create another table to report part of the sale from the data below.
Table 1
LOC# ITEM sale_total FiscalYear FiscalPrd TYPE O_R DESC LFT_EXP METHOD PRD_MO AG_PCNT PLAN_ID YEARS STATUS
33 17879 12203.57 2017 3 A O Plan A L W 120 100.00 6 10 N
33 17903 579.97 2017 3 A O Plan A L W 120 100.00 6 10 N
33 18870 799.60 2017 3 A O Plan A L W 120 100.00 6 10 N
33 19739 319.95 2017 3 A B Plan C E F 36 100.00 8 3 N
33 21585 559.96 2017 3 B O Plan B E N 0 100.00 10 0 N
A percentage of the sale_total from table above needs to be distributed based on the table below (I can also include the YR01-YR10 columns in the table above if it make things simpler).
Table 2
PLAN_ID EFDATE MONTHS METHOD EPERCENT YR01 YR02 YR03 YR04 YR05 YR06 YR07 YR08 YR09 YR10
6 2007-08-01 120 W 100.00 40.00 20.00 11.00 8.00 6.00 5.00 4.00 3.00 2.00 1.00
8 2012-11-12 36 F 100.00 33.00 33.00 34.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
10 2015-10-01 0 N 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
So my end result would look like below for LOC#33 and item 18870: (So the calculation is based on the plan. For this specific example, item 18870 falls under plan 6 (table 1). Table 2 has the distribution of all plans. We can see it spreads over 120 months and YR01-YR10 has the yearly percent distribution. Now from the sales number for 18870 from table 1, 799.60, distribution math for year 1 is (799.60 x 0.4) / 12 = 26.65. Same method follows up to year 10 for this plan and up to year 3 for plan 8. For the 10 year plan, it will create 120 input records. 1 for each month for each item, location)
LOC# ITEM FiscalYear FiscalPrd SALES
33 18870 2017 4 26.65
33 18870 2017 5 26.85
33 18870 2017 6 26.85
.............................................
.............................................
33 18870 2017 11 26.85
33 18870 2017 12 26.85
33 18870 2018 1 13.33
33 18870 2018 2 13.33
.............................................
.............................................
33 18870 2018 11 13.33
33 18870 2018 12 13.33
.............................................
.............................................
33 18870 2027 2 0.67
33 18870 2027 3 0.67
It will distribute that income over 120 months at the percentage dictated by the table 2 for planID 6. for planID 8, it will do the same math over 36 months.
The percentages can change over time and a user will manage the plans. There are other locations and the first table will include all location for the current fiscal period and all items (3 max as shows in Table 2). I created a status columns so I can mark if once the data is processed.
When comes the next fiscal period sales, the program will update the above result set sales numbers to include new sales. It will be run once a month to generate the above result.
Would greatly appreciate some direction as I got up to this point and not sure how to approach from here.
Thanks a bunch.
#ZLK I saved the first run in a temp table, then added the following rows
(33, 17879, 10000.00, 2017, 4, 6, 10),
(33, 17903, 500.00, 2017, 4, 6, 10),
(33, 18870, 800.00, 2017, 4, 6, 10),
(33, 19739, 300.00, 2017, 4, 8, 3),
(33, 21585, 500.00, 2017, 4, 10, 0);
This the save first set of item, location with different sales number in fiscal period 4. the first set was inserted into a table #finalDist, the second uses the following query to insert and update.
begin tran
if exists (select * FROM #finalDist AGE
INNER JOIN #dist PrdAg on PrdAg.Loc = AGE.Loc
and PrdAg.Item = AGE.Item
and PrdAg.FiscalYear = AGE.FiscalYear
and PrdAg.FiscalPrd = AGE.FiscalPrd)
begin
UPDATE AGE
SET AGE.SALES = AGE.SALES + PrdAg.SALES
FROM #finalDist AGE
INNER JOIN #dist PrdAg on PrdAg.Loc = AGE.Loc
and PrdAg.Item = AGE.Item
and PrdAg.FiscalYear = AGE.FiscalYear
and PrdAg.FiscalPrd = AGE.FiscalPrd
end
else
begin
INSERT INTO #finalDist (Loc, Item, FiscalYear, FiscalPrd, SALES)
SELECT Loc, Item, FiscalYear, FiscalPrd, SALES from #dist PrdAg
WHERE NOT EXISTS (SELECT AGE.Item FROM #finalDist AGE WHERE PrdAg.Loc = AGE.Loc
and PrdAg.Item = AGE.Item
and PrdAg.FiscalYear = AGE.FISCALYear
and PrdAg.FiscalPrd = AGE.FiscalPrd)
end
commit tran
I realize I can't do if else as I need to do both insert and update. It will update everything except the fiscal period 3, then it will insert four rows for this case
Loc Item FiscalYear FiscalPrd SALES
33 18870 2027 4 0.66666666666
33 19739 2020 4 8.50000000000
33 17903 2027 4 0.41666666666
33 17879 2027 4 8.33333333333
update look like this
33 17879 2017 4 406.78566666666 -- this row wasn't updated
33 17879 2017 5 740.11899999999
One way you can do it is like this:
DECLARE #T TABLE (Loc INT, Item INT, Sales_Total DECIMAL(10, 2), FiscalYear INT, FiscalPrd INT, Plan_ID INT, YEARS INT);
INSERT #T (Loc, Item, Sales_Total, FiscalYear, FiscalPrd, Plan_ID, YEARS) VALUES
(33, 17879, 12203.57, 2017, 3, 6, 10),
(33, 17903, 579.97, 2017, 3, 6, 10),
(33, 18870, 799.60, 2017, 3, 6, 10),
(33, 19739, 319.95, 2017, 3, 8, 3),
(33, 21585, 559.96, 2017, 3, 10, 0);
DECLARE #T2 TABLE (PLAN_ID INT, YR01 DECIMAL(4, 2), YR02 DECIMAL(4, 2), YR03 DECIMAL(4, 2), YR04 DECIMAL(4, 2), YR05 DECIMAL(4, 2), YR06 DECIMAL(4, 2), YR07 DECIMAL(4, 2), YR08 DECIMAL(4, 2), YR09 DECIMAL(4, 2), YR10 DECIMAL(4, 2));
INSERT #T2 (PLAN_ID, YR01, YR02, YR03, YR04, YR05, YR06, YR07, YR08, YR09, YR10) VALUES
(6, 40.00, 20.00, 11.00, 8.00, 6.00, 5.00, 4.00, 3.00, 2.00, 1.00),
(8, 33.00, 33.00, 34.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00),
(10, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00);
WITH CTE(N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) AS A(B)),
CTE2(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM CTE AS A CROSS JOIN CTE) -- Numbers 1-121
SELECT T.Loc,
T.Item,
FiscalYear = DATEPART(YEAR, DATEADD(MONTH, CTE2.N, DATEFROMPARTS(T.FiscalYear, T.FiscalPrd, 1))),
FiscalPrd = DATEPART(MONTH, DATEADD(MONTH, CTE2.N, DATEFROMPARTS(T.FiscalYear, T.FiscalPrd, 1))),
SALES = T.Sales_Total * C.Vals / 100 / 12
FROM #T AS T
JOIN CTE2
ON CTE2.N <= T.YEARS * 12
JOIN
(
SELECT T.PLAN_ID, C.Y, C.Vals
FROM #T2 AS T
CROSS APPLY (VALUES (1, YR01), (2, YR02), (3, YR03), (4, YR04), (5, YR05), (6, YR06), (7, YR07), (8, YR08), (9, YR09), (10, YR10)) AS C(Y, Vals) -- Unpivot
) AS C
ON C.PLAN_ID = T.PLAN_ID
AND C.Y = (CTE2.N + 11) / 12
ORDER BY T.Loc, T.Item, CTE2.N;
Essentially you want to get a list of numbers (up to 120 here but if there's more than 10 years, you would need more) and cross join it to your table. Then unpivot the values in table2 and link them to the numbers table in (grouping them by years).
EDIT:
Taking into account that values can change and assuming the end date is still the same and doesn't increase, this is what I believe you're looking for:
DECLARE #T TABLE (Loc INT, Item INT, Sales_Total DECIMAL(10, 2), FiscalYear INT, FiscalPrd INT, Plan_ID INT, YEARS INT);
INSERT #T (Loc, Item, Sales_Total, FiscalYear, FiscalPrd, Plan_ID, YEARS) VALUES
(33, 17879, 12203.57, 2017, 3, 6, 10),
(33, 17903, 579.97, 2017, 3, 6, 10),
(33, 18870, 799.60, 2017, 3, 6, 10),
(33, 19739, 319.95, 2017, 3, 8, 3),
(33, 21585, 559.96, 2017, 3, 10, 0),
(33, 17879, 10000.00, 2017, 4, 6, 10),
(33, 17903, 500.00, 2017, 4, 6, 10),
(33, 21585, 500.00, 2017, 4, 10, 0),
(33, 17879, 5000.00, 2017, 5, 6, 10),
(33, 17879, 6900.00, 2017, 7, 6, 10);
DECLARE #T2 TABLE (PLAN_ID INT, YR01 DECIMAL(4, 2), YR02 DECIMAL(4, 2), YR03 DECIMAL(4, 2), YR04 DECIMAL(4, 2), YR05 DECIMAL(4, 2), YR06 DECIMAL(4, 2), YR07 DECIMAL(4, 2), YR08 DECIMAL(4, 2), YR09 DECIMAL(4, 2), YR10 DECIMAL(4, 2));
INSERT #T2 (PLAN_ID, YR01, YR02, YR03, YR04, YR05, YR06, YR07, YR08, YR09, YR10) VALUES
(6, 40.00, 20.00, 11.00, 8.00, 6.00, 5.00, 4.00, 3.00, 2.00, 1.00),
(8, 33.00, 33.00, 34.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00),
(10, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00);
WITH CTE(N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) AS A(B)),
CTE2(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM CTE AS A CROSS JOIN CTE) -- Numbers 0-120
SELECT T.Loc,
T.Item,
FiscalYear = DATEPART(YEAR, DATEADD(MONTH, CTE2.N, T.FirstDate)),
FiscalPrd = DATEPART(MONTH, DATEADD(MONTH, CTE2.N, T.FirstDate)),
SALES = T.TotalToDate * C.Vals / 100 / 12
FROM
(
SELECT T.Loc,
T.Item,
T.YEARS,
T.Plan_ID,
C.TotalToDate,
FirstDate = CAST(DATEADD(MONTH, 1, CAST(MIN(FiscalYear) OVER (PARTITION BY Loc, Item) AS CHAR(4)) + '-' +
CAST(MIN(FiscalPrd) OVER (PARTITION BY Loc, Item) AS VARCHAR(2)) + '-01') AS DATE),
CurrentDate = CAST(DATEADD(MONTH, 1, CAST(FiscalYear AS CHAR(4)) + '-' + CAST(FiscalPrd AS VARCHAR(2)) + '-01') AS DATE),
C2.NextDate
FROM #T AS T
CROSS APPLY
(
SELECT SUM(Sales_Total)
FROM #T
WHERE Loc = T.Loc
AND Item = T.Item
AND FiscalYear * 12 + FiscalPrd <= T.FiscalYear * 12 + T.FiscalPrd
) AS C(TotalToDate)
OUTER APPLY
(
SELECT CAST(DATEADD(MONTH, 1, CAST(MIN(FiscalYear) AS CHAR(4)) + '-' +
CAST(MIN(FiscalPrd) AS VARCHAR(2)) + '-01') AS DATE)
FROM #T
WHERE Loc = T.Loc
AND Item = T.Item
AND FiscalYear * 12 + FiscalPrd > T.FiscalYear * 12 + T.FiscalPrd
) AS C2(NextDate)
) AS T
JOIN CTE2
ON CTE2.N <= T.YEARS * 12 - 1
AND CTE2.N >= DATEDIFF(MONTH, T.FirstDate, T.CurrentDate)
AND DATEADD(MONTH, CTE2.N, T.FirstDate) < COALESCE(T.NextDate, DATEADD(MONTH, T.YEARS * 12, T.FirstDate))
JOIN
(
SELECT T.PLAN_ID, C.Y, C.Vals
FROM #T2 AS T
CROSS APPLY (VALUES (1, YR01), (2, YR02), (3, YR03), (4, YR04), (5, YR05), (6, YR06), (7, YR07), (8, YR08), (9, YR09), (10, YR10)) AS C(Y, Vals) -- Unpivot
) AS C
ON C.PLAN_ID = T.PLAN_ID
AND C.Y = (CTE2.N + 12) / 12
ORDER BY T.Loc, T.Item, CTE2.N;
SECOND EDIT (Modified to have the start date be the month declared, e.g. March 2017 means the plan starts in March 2017 instead of April 2017. The only difference is adjusting the row_number joins):
/*
#PlanTable: A static table for plans.
*/
DECLARE #PlanTable TABLE (PLAN_ID INT, YR01 DECIMAL(4, 2), YR02 DECIMAL(4, 2), YR03 DECIMAL(4, 2), YR04 DECIMAL(4, 2), YR05 DECIMAL(4, 2), YR06 DECIMAL(4, 2), YR07 DECIMAL(4, 2), YR08 DECIMAL(4, 2), YR09 DECIMAL(4, 2), YR10 DECIMAL(4, 2));
INSERT #PlanTable (PLAN_ID, YR01, YR02, YR03, YR04, YR05, YR06, YR07, YR08, YR09, YR10) VALUES
(6, 40.00, 20.00, 11.00, 8.00, 6.00, 5.00, 4.00, 3.00, 2.00, 1.00),
(8, 33.00, 33.00, 34.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00),
(10, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00);
/*
#RecordsToInsert: The values you're inserting into your final table. Starting with FiscalYear 2017 and FiscalPrd 3 as an example.
*/
DECLARE #RecordsToInsert TABLE (Loc INT, Item INT, Sales_Total DECIMAL(10, 2), FiscalYear INT, FiscalPrd INT, Plan_ID INT, YEARS INT);
INSERT #RecordsToInsert (Loc, Item, Sales_Total, FiscalYear, FiscalPrd, Plan_ID, YEARS) VALUES
(33, 17879, 12203.57, 2017, 3, 6, 10),
(33, 17903, 579.97, 2017, 3, 6, 10),
(33, 18870, 799.60, 2017, 3, 6, 10),
(33, 19739, 319.95, 2017, 3, 8, 3),
(33, 21585, 559.96, 2017, 3, 10, 0);
/*
#FinalTable: This is the table you're using to insert the data.
*/
DECLARE #FinalTable TABLE (Loc INT, Item INT, FiscalYear INT, FiscalPrd INT, SALES DECIMAL(10, 2));
/*
Start by inserting the first lot of information into the final table.
*/
WITH CTE(N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) AS A(B)),
CTE2(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM CTE AS A CROSS JOIN CTE) -- Numbers 0-120
INSERT #FinalTable (Loc, Item, FiscalYear, FiscalPrd, SALES)
SELECT T.Loc,
T.Item,
FiscalYear = DATEPART(YEAR, DATEADD(MONTH, CTE2.N, CAST(T.FiscalYear AS CHAR(4)) + '-' + CAST(T.FiscalPrd AS VARCHAR(2)) + '-01')),
FiscalPrd = DATEPART(MONTH, DATEADD(MONTH, CTE2.N, CAST(T.FiscalYear AS CHAR(4)) + '-' + CAST(T.FiscalPrd AS VARCHAR(2)) + '-01')),
SALES = T.Sales_Total * C.Vals / 100 / 12
FROM #RecordsToInsert AS T
JOIN CTE2
ON CTE2.N <= T.YEARS * 12 - 1
JOIN
(
SELECT T.PLAN_ID, C.Y, C.Vals
FROM #PlanTable AS T
CROSS APPLY (VALUES (1, YR01), (2, YR02), (3, YR03), (4, YR04), (5, YR05), (6, YR06), (7, YR07), (8, YR08), (9, YR09), (10, YR10)) AS C(Y, Vals) -- Unpivot
) AS C
ON C.PLAN_ID = T.PLAN_ID
AND C.Y = CTE2.N / 12 + 1
ORDER BY T.Loc, T.Item, CTE2.N;
/*
Next we want to insert records for the next FiscalPrd, so we get rid of the last ones and put in FiscalYear 2017, FiscalPrd 4.
*/
DELETE #RecordsToInsert;
INSERT #RecordsToInsert (Loc, Item, Sales_Total, FiscalYear, FiscalPrd, Plan_ID, YEARS) VALUES
(33, 17879, 10000.00, 2017, 4, 6, 10),
(33, 17903, 500.00, 2017, 4, 6, 10),
(33, 18870, 800.00, 2017, 4, 6, 10),
(33, 19739, 300.00, 2017, 4, 8, 3),
(33, 21585, 500.00, 2017, 4, 10, 0);
/*
Then we update the final table with the new sales total, ignoring periods that were prior to the fiscal year and period being inserted.
*/
UPDATE T
SET SALES = SALES_NEW
FROM (
SELECT FT.Loc,
FT.Item,
FT.FiscalYear,
FT.FiscalPrd,
FT.SALES,
SALES_NEW = (SUM(FT.SALES) OVER (PARTITION BY FT.Loc, FT.Item) + R.Sales_Total) * C.Vals / 100 / COUNT(1) OVER (PARTITION BY FT.Loc, FT.Item, (FT.RN + 11) / 12)
FROM (SELECT *, RN = ROW_NUMBER() OVER (PARTITION BY Loc, Item ORDER BY FiscalYear, FiscalPrd) FROM #FinalTable) AS FT
JOIN #RecordsToInsert AS R
ON R.Loc = FT.Loc
AND R.Item = FT.Item
AND R.FiscalYear * 12 + R.FiscalPrd <= FT.FiscalYear * 12 + FT.FiscalPrd
JOIN
(
SELECT T.PLAN_ID, C.Y, C.Vals
FROM #PlanTable AS T
CROSS APPLY (VALUES (1, YR01), (2, YR02), (3, YR03), (4, YR04), (5, YR05), (6, YR06), (7, YR07), (8, YR08), (9, YR09), (10, YR10)) AS C(Y, Vals) -- Unpivot
) AS C
ON C.PLAN_ID = R.PLAN_ID
AND C.Y = (FT.RN + 11) / 12
) T;
/*
For the first year, the sales for 2017/5 onwards have changed to (totalsales - firstmonth) * 40% / 11
For the second years onward, the sales have changed to totalsales * whatever% / 12
The first month of the first year remains the same.
*/
SELECT Loc, Item, FiscalYear, FiscalPrd, SALES
FROM #FinalTable
ORDER BY Loc, Item, FiscalYear, FiscalPrd;

SELECT TOP 20 rows for each group [duplicate]

This question already has answers here:
Select top 10 records for each category
(14 answers)
Closed 5 years ago.
I have a table with 3 columns Item, City and VisitNumber.
In this table there are a lot of records and I need to select top 20 items of each city (according to their visit numbers).
For example if there are 100 items in Washington and 250 items in New York and 500 items in Los Angeles, I need to select 60 most-visited rows for each city (20 for Washington, 20 for New York, 20 for Los Angeles)
How is it possible in TSQL?
The easiest way would be to use the row_number() window function to number the rows for each city according to their visitnumber descending and use that as a filter. This query should work in any SQL Server version from 2005 onwards.
select *
from (
select *, r = row_number() over (partition by City order by VisitNumber desc)
from your_table
) a
where r <= 20
and City in ('Washington', 'New York', 'Los Angeles')
This would select the top 20 items for each city specified in the where clause.
In one select:
select top 1 with ties
Item, City, VisitNumber
from
your_table
where
City in ('Washington', 'New York', 'Los Angeles')
order by
case
when row_number() over(partition by City order by VisitNumber desc) <= 20
then 0
else 1
end;
A complete answer might look like :
declare #Visists table (
Item int,
City varchar(20),
VisitNumber int
)
insert into #Visists values
(1, 'Washington', 11),
(2, 'Washington', 22),
(3, 'Washington', 33),
(4, 'Washington', 44),
(5, 'Washington', 55),
(6, 'New York', 66),
(7, 'New York', 77),
(8, 'New York', 88),
(9, 'New York', 99),
(10, 'New York', 5),
(11, 'Los Angeles', 12),
(12, 'Los Angeles', 23),
(13, 'Los Angeles', 34),
(14, 'Los Angeles', 45),
(15, 'Los Angeles', 56),
(16, 'Chicago', 9),
(17, 'Chicago', 7),
(18, 'Chicago', 3),
(19, 'Chicago', 2),
(20, 'Chicago', 9);
declare #TopVisitsPerCity int = 3;
declare #TopOfCities int = 3;
with TopVisitsPerCity as
(
select top 1 with ties
Item, City, VisitNumber
from
#Visists
order by
case
when row_number() over(partition by City order by VisitNumber desc) <= #TopVisitsPerCity
then 0
else 1
end
)
select top (#TopOfCities * #TopVisitsPerCity)
*
from
TopVisitsPerCity
order by
sum(VisitNumber) over (partition by City) desc;

Resources