I have a table which stores information as follows and has ID as the primary key:
Link for the table view: https://drive.google.com/file/d/0B4UzXmbWLTJZaU84WnVZMUJDT3M/view?usp=sharing
ID ScheduleDate WorkArea Employee1 Hours1 Employee2 Hours2 Employee3 Hours3 Employee4 Hours4 Employee5 Hours5 Employee6 Hours6 Employee7 Hours7 Employee8 Hours8
1 7/1/2014 W1 A 8 B 7 C 4 D 3 NULL 0 NULL 0 NULL 0 NULL 0
2 7/1/2014 W2 B 8 C 8 0 0 0 0 NULL
3 7/1/2014 W3 C 8 A 8 E 8 F 8 NULL NULL NULL NULL NULL NULL NULL NULL
4 7/1/2014 W4 D 8 B 8 F 8 NULL NULL NULL NULL NULL NULL
5 7/1/2014 W5 E 8 C 8 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
6 7/1/2014 W6 F 8 D 8 8 NULL NULL NULL NULL NULL NULL NULL NULL NULL
7 8/1/2014 W1 G 4 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
8 8/1/2014 W2 A 4 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
9 8/1/2014 W3 B 8 F 8 8 8 NULL NULL NULL NULL NULL NULL NULL NULL
For any particular ScheduleDate, there can be only one WorkArea (combination of ScheduleDate and WorkArea is unique). Now, I want to check if the sum of hours of the particular employee is greater than 8 hours or not in any single date. For example, the sum of hours of employee A for the particular date (can be hour1, hour2 or anything based on employee's placement in the table) should not be more than 8 hours. How do I check that?
Please help.
Thanks
You don't really strictly need the aliases on each of the union-ed queries:
with t as (
select ScheduleDate, Workarea, Employee1 as Employee, Hours1 as Hrs union all
select ScheduleDate, Workarea, Employee2 as Employee, Hours2 as Hrs union all
...
select ScheduleDate, Employee8 as Employee, Hours8 as Hrs
)
select ScheduleDate, Employee, sum(Hrs) as [Hours]
from t
group by ScheduleDate, Employee
having sum(Hrs) > 8
Related
It should be very easy, but I am stucked in this.
It is simple as the image, but I have a column named "category" and once the row has a category, I want this value repeated for 'n' times, let's say 10 times (or whatever I want), in a new column.
I've tried to use FIRST_VALUE(), but there is no pattern about when this category will appear, so most of times I have 'null' as a repetition.
I've seen ROW_NUMBER() OVER(PRECEDING AND FOLLOWING) but I can't use a string in this, just an aggregation and I don't want to calculate, I wanna classify. I even tried using CASE WHEN xxx category * 10 etc, or category + 10 but of course doesn't work.
Any suggestion? Thanks!
What I've tried:
WITH table1 AS(
SELECT
date,
hour,
minute,
category,
ROW_NUMBER() OVER() AS rn
FROM table1),
table2 AS(
SELECT
*,
CASE
WHEN category IS NOT NULL THEN 1
ELSE 0
END AS flag_category
FROM table1)
SELECT
*,
CASE
WHEN flag_category = 1
THEN (SELECT
a.category,
FROM table2 AS a
INNER JOIN table2 AS b
ON a.rn = b.rn + 10)
ELSE '-'
END AS category_repetition
FROM table2
image explication here
W H A T I H A V E WHAT I WANT
date hour minute qty category category_repetition
20210412 0 0 2 null null
20210412 0 1 0 null null
20210412 0 2 6 null null
20210412 0 3 7 null null
20210412 0 4 7 null null
20210412 0 5 6 null null
20210412 0 6 3 null null
20210412 0 7 8 null null
20210412 0 8 4 null null
20210412 0 9 3 category A category A
20210412 0 10 4 null category A
20210412 0 11 0 null category A
20210412 0 12 5 null category A
20210412 0 13 2 null category A
20210412 0 14 3 null category A
20210412 0 15 3 null category A
20210412 0 16 4 null category A
20210412 0 17 3 null category A
20210412 0 18 5 null category A
20210412 0 19 4 null category A
You seem to want last_value(ignore nulls):
select t.*,
last_value(category ignore nulls) over (order by date, hour, minute) as category_repetition
from t;
I'm not sure what the "10" means in the question. This should produce the data that you want, based on the sample data and results.
I have written a query that returns a resultset of the top 10 values. This works great, but where a resultset returns a list of values that is smaller than 10 items then I would like the query to return placeholder values to pas the resultset out to ten values i.e. NULLS.
Current resultset:
SENDBottom10Prog CFC 11 Business Surname1 Forename1 11MO 50 2 4 U -4.00
SENDBottom10Prog CIN 11 Business Surname2 Forename2 11MO 86.9 0 4 2 -2.00
SENDBottom10Prog N 11 Business Surname3 Forename3 11MC 100 0 3 2 -1.00
SENDBottom10Prog N 11 Business Surname4 Forename4 11MO 97.62 5 4 6 2.00
Desirable resultset:
SENDBottom10Prog CFC 11 Business Surname1 Forename1 11MO 50 2 4 U -4.00
SENDBottom10Prog CIN 11 Business Surname2 Forename2 11MO 86.9 0 4 2 -2.00
SENDBottom10Prog N 11 Business Surname3 Forename3 11MC 100 0 3 2 -1.00
SENDBottom10Prog N 11 Business Surname4 Forename4 11MO 97.62 5 4 6 2.00
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
Here is my code so far:
DECLARE
#AcademicYear varchar(9) = '2019/2020',
#Collection varchar(50) = 'autumn',
#StuYear VARCHAR(2) = '11';
Select 'SENDBottom10Prog' as List, SG, Year, Subject, Surname, Forename, Form, [AM/PM], Behaviour, FFT20, Prediction, Residual
From (
SELECT s.sg, s.Year,r.Subject as 'Subject', s.Surname, s.Forename, s.Form,s.attendance as 'AM/PM', s.behaviour, r.Target as FFT20, r.Prediction, g3.Points-g2.Points as Residual, g3.graderank, row_number() over(partition by r.subject order by s.year, r.subject, cast(g3.Points-g2.Points as decimal) asc, g3.graderank asc, Attendance asc, Behaviour, s.Surname, s.Forename) as rn
FROM Results r
LEFT JOIN Grades g1
ON r.Result = g1.Grade
LEFT JOIN Grades g2
ON r.Target = g2.Grade
LEFT JOIN Grades g3
ON r.Prediction = g3.Grade
LEFT JOIN students s
ON r.UPN = s.UPN
WHERE r.AcademicYear = #AcademicYear
AND s.AcademicYear = #AcademicYear
AND r.Collection = #Collection
AND s.year=#StuYear
AND SEND='Y'
AND s.NotIncluded = 'N'
) as T
where T.rn <=10;
If you want to get exactly ten rows, but don't have them, then you need to construct them. Here is one method:
with t as (
< your query here >
)
select t.*
from (values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)
) v(n) left join
t
on t.rn = v.n
order by v.n;
I have a table where I have all the customers and a table where I have all their restrictions.
CUSTOMER
customer_id customer_name
1 name 1
2 name 2
CUSTOMER_RESTRICTIONS
rest_type day_of_week hour_start hour_stop customer_id
TYPE1 0 08:00 12:00 1
TYPE1 0 13:00 17:00 1
TYPE2 0 17:00 23:59 1
Problem: I only have a record for a restriction type and a customer when the customer has a restriction and this is a problem in the visualization I want to build.
I need every customer, every day and every restriction type, even when there is no restriction. In that case hour_start and hour_stop would be NULL.
For the tables shown, the output would be
rest_type day_of_week hour_start hour_stop customer_id
TYPE1 0 08:00 12:00 1
TYPE1 0 08:00 12:00 1
TYPE1 1 NULL NULL 1
TYPE1 2 NULL NULL 1
TYPE1 3 NULL NULL 1
TYPE1 4 NULL NULL 1
TYPE1 5 NULL NULL 1
TYPE1 6 NULL NULL 1
TYPE1 1 NULL NULL 1
TYPE1 2 NULL NULL 1
TYPE1 3 NULL NULL 1
TYPE1 4 NULL NULL 1
TYPE1 5 NULL NULL 1
TYPE2 0 NULL NULL 1
TYPE2 1 NULL NULL 1
TYPE2 2 NULL NULL 1
TYPE2 3 NULL NULL 1
TYPE2 4 NULL NULL 1
TYPE2 5 NULL NULL 1
TYPE2 6 NULL NULL 1
TYPE1 0 NULL NULL 2
TYPE1 1 NULL NULL 2
TYPE1 2 NULL NULL 2
TYPE1 3 NULL NULL 2
TYPE1 4 NULL NULL 2
TYPE1 5 NULL NULL 2
TYPE1 6 NULL NULL 2
TYPE2 0 NULL NULL 2
TYPE2 1 NULL NULL 2
TYPE2 2 NULL NULL 2
TYPE2 3 NULL NULL 2
TYPE2 4 NULL NULL 2
TYPE2 5 NULL NULL 2
TYPE2 6 NULL NULL 2
How can I achieve that? I couldn't even start to build this query.
Essentially you need to start with the data you must have and left join the optional data. E.g., something like this:
select c.customer_id
,r.[rest_type]
,d.[day_of_week]
,r.[hour_start]
,r.[hour_stop]
from CUSTOMER c
cross apply (
select 0 as day_of_week
union all select 1
union all select 2
union all select 3
union all select 4
union all select 5
union all select 6
) d
left join CUSTOMER_RESTRICTIONS r on c.customer_id = r.customer_id and d.day_of_week = r.day_of_week
Output:
customer_id rest_type day_of_week hour_start hour_stop
----------- --------- ----------- ---------- ---------
1 TYPE1 0 08:00 12:00
1 TYPE1 0 13:00 17:00
1 TYPE2 0 17:00 23:59
1 NULL 1 NULL NULL
1 NULL 2 NULL NULL
1 NULL 3 NULL NULL
1 NULL 4 NULL NULL
1 NULL 5 NULL NULL
1 NULL 6 NULL NULL
If there are only type rest_types, you don't have a lookup table for them, and you want to show a row for each, you would do:
select c.customer_id
,t.[rest_type]
,d.[day_of_week]
,r.[hour_start]
,r.[hour_stop]
from CUSTOMER c
cross apply (
select 0 as day_of_week
union all select 1
union all select 2
union all select 3
union all select 4
union all select 5
union all select 6
) d
cross apply (
select 'TYPE1' as rest_type
union all select 'TYPE2'
) t
left join CUSTOMER_RESTRICTIONS r on c.customer_id = r.customer_id
and d.day_of_week = r.day_of_week
and t.rest_type = r.rest_type
(select rest_type, day_of_week,
hour_start ,
hour_stop
from table A
where rest_type IS NOT NULL)
Union
(select rest_type,
day_of_week,
NULL ,NULL
from table A
where rest_type IS NULL)
Is this what you want ?
First off, I wouldn't store rest type as you are, that is a bad habit, it should be a reference table!
You need to cross apply to get all your possible combinations, and then add in the values you DO have...
DECLARE #Customer TABLE (Id INT IDENTITY(1,1), Name NVARCHAR(100))
DECLARE #Rest TABLE (Id INT IDENTITY(1,1), Name NVARCHAR(100))
DECLARE #Restrictions TABLE (Id INT IDENTITY(1,1), RestID INT, CustomerID INT, Day_of_Week TINYINT, hour_start TIME, hour_end TIME)
INSERT INTO #Customer (NAME)
VALUES('JOHN'),('SUSAN')
INSERT INTO #Rest (NAME)
VALUES ('TYPE A'),('TYPE B')
INSERT INTO #Restrictions (RestID,CustomerID,Day_of_Week,hour_start,hour_end)
VALUES (1,1,0,'08:00','12:00'),
(1,1,0,'13:00','17:00'),
(1,2,0,'17:00','23:59')
;WITH DaysofWeek AS
(
SELECT 0 AS dow
UNION ALL
SELECT dow+1
FROM DaysofWeek
WHERE dow<5
)
SELECT *
FROM #Customer C
CROSS APPLY #Rest R
CROSS APPLY DaysofWeek D
LEFT JOIN #Restrictions X
ON X.Day_of_Week=D.dow
AND X.CustomerID=C.Id
AND X.RestID=R.Id
ORDER BY C.Id, D.dow, R.Id
I have a table that looks like
Year Month ID Date Status
--------------------------------------
2013 8 99999 8/1/2013 Status A
2013 9 99999 NULL NULL
2013 10 99999 NULL NULL
2013 11 99999 NULL NULL
2013 12 99999 NULL NULL
2014 1 99999 NULL NULL
2014 2 99999 2/5/2014 Status B
2014 3 99999 NULL NULL
2014 4 99999 NULL NULL
2014 5 99999 NULL NULL
2014 6 99999 NULL NULL
2014 7 99999 NULL NULL
I want to add a column that will give me the number of the status, repeated until the next occurrence of a status, where it will add 1.
Result:
Year Month ID Date Status Value
--------------------------------------------
2013 8 99999 8/1/2013 Status A 1
2013 9 99999 NULL NULL 1
2013 10 99999 NULL NULL 1
2013 11 99999 NULL NULL 1
2013 12 99999 NULL NULL 1
2014 1 99999 NULL NULL 1
2014 2 99999 2/5/2014 Status B 2
2014 3 99999 NULL NULL 2
2014 4 99999 NULL NULL 2
2014 5 99999 NULL NULL 2
2014 6 99999 NULL NULL 2
2014 7 99999 NULL NULL 2
The Nulls are whats throwing me off...Thanks for the help!
Edit:
Here's my current query:
DECLARE #DateStart DATETIME
DECLARE #DateEnd DATETIME
SET #DateStart = '8/1/2013'
SET #DateEnd = '7/1/2014'
SELECT
P.Year, P.Month, P.ID,
PP.MaxStatusDate,
Status
FROM
(SELECT
*
FROM
(SELECT DISTINCT
year, Month
FROM
lu_Calendar
WHERE
Date BETWEEN #DateStart AND #DateEnd) AS A
CROSS JOIN
(SELECT DISTINCT
ID
FROM
dbo.StatusChangeData) AS B
) AS P
LEFT JOIN
(SELECT
yr, mnth, MaxStatusDate, Status, A.ID
FROM
(SELECT
ID, YEAR([ModifiedDate]) AS yr,
MONTH(ModifiedDate) AS mnth,
MAX([ModifiedDate]) AS MaxStatusDate
FROM
dbo.StatusChangeData
GROUP BY
ID, YEAR([ModifiedDate]), MONTH(ModifiedDate)) AS A
INNER JOIN
dbo.StatusChangeData sce ON sce.ID = A.ID AND A.MaxStatusDate = sce.[ModifiedDate]
) AS PP ON P.Month = pp.mnth AND P.YEAR = PP.yr AND P.ID = PP.ID
WHERE
P.ID = 99999
You can do this with a correlated subquery. Essentially, this counts the number of not-NULL values before any given value:
select scd.*,
(select count(*)
from StatusChangeData scd2
where scd2.id = scd.id and
scd2.status is not null and
scd2.year*100+scd2.month <= scd.year*100+scd.month
) as value
from StatusChangeData scd;
I am trying to find the Chi-Square test from my following SQL Server Query on the sample data:
SELECT sessionnumber, sessioncount, timespent, expected, dev, dev*dev/expected as chi_square
FROM (SELECT clusters.sessionnumber, clusters.sessioncount, clusters.timespent,
(dim1.cnt * dim2.cnt * dim3.cnt)/(dimall.cnt*dimall.cnt) as expected,
clusters.cnt-(dim1.cnt * dim2.cnt * dim3.cnt)/(dimall.cnt*dimall.cnt) as dev
FROM clusters JOIN
(SELECT sessionnumber, SUM(cnt) as cnt FROM clusters
GROUP BY sessionnumber) dim1 ON clusters.sessionnumber = dim1.sessionnumber JOIN
(SELECT sessioncount, SUM(cnt) as cnt FROM clusters
GROUP BY sessioncount) dim2 ON clusters.sessioncount = dim2.sessioncount JOIN
(SELECT timespent, SUM(cnt) as cnt FROM clusters
GROUP BY timespent) dim3 ON clusters.timespent = dim3.timespent CROSS JOIN
(SELECT SUM(cnt) as cnt FROM clusters) dimall) a
My table has this sort of sample data:
sessionnumber sessioncount timespent cnt
1 17 28 NULL
2 22 8 NULL
3 1 1 NULL
4 1 1 NULL
5 8 111 NULL
6 8 65 NULL
7 11 5 NULL
8 1 1 NULL
9 62 64 NULL
10 6 42 NULL
The problem is that this query works fine but it gives wrong output or you can say no output at all. The output it gives my is like:
sessionnumber sessioncount timespent expected dev chi_square
1 17 28 NULL NULL NUL
2 22 8 NULL NULL NULL
3 1 1 NULL NULL NULL
4 1 1 NULL NULL NULL
5 8 111 NULL NULL NULL
6 8 65 NULL NULL NULL
7 11 5 NULL NULL NULL
8 1 1 NULL NULL NULL
9 62 64 NULL NULL NULL
10 6 42 NULL NULL NULL
How can I get rid of this problem because I tried my best at all! Thanks in advance telling me what I' doing wrong!
In your sample data, cnt is NULL, so the results are also NULL. You can replace these NULL values with a default value (1 for example, I don't know what is the context) using ISNULL, like
SELECT sessionnumber, SUM(ISNULL(cnt, 1)) as cnt FROM clusters GROUP BY sessionnumber