Creating a time table using SQL - sql

I want to create a time table for my university's modules in SQL Server Management Studio using a query.
This is my first time programming in SQL and don't know much about it. I have created the database as well as the tables I want to use, using the following code:
USE master
GO
IF EXISTS (SELECT * FROM sys.databases WHERE name = 'myTimetable')
DROP DATABASE myTimetable
GO
CREATE DATABASE myTimetable
GO
USE myTimetable
GO
CREATE TABLE DayTable
(
WeekDay_ID int Identity (1,1) PRIMARY KEY NOT NULL,
Day_Name varchar(10) NOT NULL
)
GO
CREATE TABLE TimeRangeTable
(
DayTime_ID int Identity (1,1) PRIMARY KEY NOT NULL,
TimeInterval varchar(20) NOT NULL
)
GO
CREATE TABLE SubjectTable
(
Course_ID int Identity (1,1) PRIMARY KEY NOT NULL,
CourseCode varchar (10),
CourseName varchar (255) NOT NULL
)
GO
CREATE TABLE ScheduleTable
(
WeekDay_ID int references DayTable(WeekDay_ID),
DayTime_ID int references TimeRangeTable(DayTime_ID),
Course_ID int references SubjectTable(Course_ID),
)
GO
The tables was created correctly and I managed to insert the correct data into the tables, except for my ScheduleTable (the last table created in the above sample code).
Here is the SQL code I used to insert the data:
insert into DayTable values ('Monday')
insert into DayTable values ('Teusday')
insert into DayTable values ('Wensday')
insert into DayTable values ('Thursday')
insert into DayTable values ('Friday')
insert into DayTable values ('Saterday')
insert into DayTable values ('Sunday')
insert into TimeRangeTable values ('07:30 - 08:20')
insert into TimeRangeTable values ('08:30 - 09:20')
insert into TimeRangeTable values ('09:30 - 10:20')
insert into TimeRangeTable values ('10:30 - 11:20')
insert into TimeRangeTable values ('11:30 - 12:20')
insert into TimeRangeTable values ('12:30 - 13:20')
insert into TimeRangeTable values ('13:30 - 14:20')
insert into TimeRangeTable values ('14:30 - 15:20')
insert into TimeRangeTable values ('15:30 - 16:20')
insert into TimeRangeTable values ('16:30 - 17:20')
insert into TimeRangeTable values ('17:30 - 18:20')
insert into SubjectTable values ('WTW115','Discrete Mathematics')
insert into SubjectTable values ('INF214','Database Design')
insert into SubjectTable values ('INL210','Information Seeking and Retreival')
insert into SubjectTable values ('INL240','Social and Ethical Impact')
insert into SubjectTable values ('INF271','System Analysis and Design')
insert into SubjectTable values ('INF154','Introduction to Programming')
-- Struling from this point onward...
insert into ScheduleTable values('1','1','1')
insert into ScheduleTable values('1','2','2')
insert into ScheduleTable values('1','3','3')
insert into ScheduleTable values('1','4','3')
insert into ScheduleTable values('1','5','3')
insert into ScheduleTable values('2','4','1')
insert into ScheduleTable values('2','5','2')
insert into ScheduleTable values('2','6','2')
insert into ScheduleTable values('2','9','4')
insert into ScheduleTable values('2','10','2')
insert into ScheduleTable values('3','1','5')
insert into ScheduleTable values('3','2','5')
insert into ScheduleTable values('3','6','1')
insert into ScheduleTable values('3','7','3')
insert into ScheduleTable values('4','1','4')
insert into ScheduleTable values('4','3','5')
It all executes and inserts the data, but when I display the data for ScheduleTable, is shows the data as Follow:
WeekDay_ID DayTime_ID Course_ID
-------------------------------------------
1 1 1 1
2 1 2 2
3 1 3 3
4 1 4 3
5 1 5 3
6 2 4 1
7 2 5 2
8 2 6 2
9 2 9 4
10 2 10 2
11 3 1 5
12 3 2 5
13 3 6 1
14 3 7 3
15 4 1 4
16 4 3 5
Where I wanted it to show the data instead of just the codes, example of what I wanted:
WeekDay_ID DayTime_ID Course_ID
--------------------------------------------
1 Monday 07:30 - 08:20 WTW115
2 Monday 08:30 - 09:20 INF214
3 Monday 09:30 - 10:20 INL210
4 Monday 10:30 - 11:20 INL210
5 Monday 11:30 - 12:20 INL210
etc...
I know it has something to do with my Schedule table but that is all I know I don't know how to display it in this way as in the example.
Any help will be appreciated.

Time for a few joins:
select --*
d.Day_Name,
tr.TimeInterval,
sbj.CourseCode, sbj.CourseName
from ScheduleTable as sch
join DayTable as d on sch.WeekDay_ID = d.WeekDay_ID
join TimeRangeTable as tr on sch.DayTime_ID = tr.DayTime_ID
join SubjectTable as sbj on sch.Course_ID = sbj.Course_ID;
You could create a view (for the aforementioned statement) for convenience:
create view TimeScheduleView
as
select
d.Day_Name,
tr.TimeInterval,
sbj.CourseCode, sbj.CourseName
from ScheduleTable as sch
join DayTable as d on sch.WeekDay_ID = d.WeekDay_ID
join TimeRangeTable as tr on sch.DayTime_ID = tr.DayTime_ID
join SubjectTable as sbj on sch.Course_ID = sbj.Course_ID;
go
select *
from TimeScheduleView;

Related

Need to get value from a lookup table

I have a table-X with ecode,emp ID ( some values)
37,10
47,20
57,30
There are 2 lookup tables
lookup table 1 has just the emp ID details( which am interested in)
10
20
so when i join..i get all the values needed (thats one part)
my result will be
37 10
47 20
second part is,
the ones which doesnt satisfy the join condition should lookup on table 2 which has
2 columns
ecode, other_codes
37 xxx
47 YYY
57 AAA
So when 30 comes in , i want to return AAA and my final dataset should be,
37, 10
47,20
57 AAA
appreciate any help!
Thanks
You can left join both tables and use CASE statement for selecting a value from one table or the other.
I've created a db-fiddle which I think exemplifies your situation based on your description: https://www.db-fiddle.com/f/ujW8Unf44CqbsiJZXqXXtK/0
Here is the code for posterity. To set up your tables:
CREATE TABLE tableX (
eCode int,
employeeId int
);
INSERT INTO tableX (eCode, employeeId) VALUES (37, 10);
INSERT INTO tableX (eCode, employeeId) VALUES (47, 20);
INSERT INTO tableX (eCode, employeeId) VALUES (57, 30);
CREATE TABLE employeeIds (employeeId int);
INSERT INTO employeeIds (employeeId) VALUES (10);
INSERT INTO employeeIds (employeeId) VALUES (20);
CREATE TABLE otherCodes (
eCode int,
other_codes varchar(10)
);
INSERT INTO otherCodes (eCode, other_codes) VALUES (37, 'XXX');
INSERT INTO otherCodes (eCode, other_codes) VALUES (47, 'YYY');
INSERT INTO otherCodes (eCode, other_codes) VALUES (57, 'AAA');
The query based on this schema:
SELECT
tx.eCode,
CASE WHEN ei.employeeId IS NULL THEN oc.other_codes ELSE ei.employeeId END as 'result'
FROM tableX tx
LEFT JOIN employeeIds ei ON tx.employeeId = ei.employeeId
LEFT JOIN otherCodes oc ON tx.eCode = oc.eCode;

I want to display the jobs running on different clusters using SQL

There are two tables job table and cluster table.Every cluster will have the different sub clusters.
LIKE
Main cluster
cluster1 cluster2 cluster3
--------------------------------------
job1 job15 job 20
. .
.
.
j14
1st cluster will have 14 jobs
2nd cluster will have 5 jobs
3rd cluster will have 5 jobs
Now I want to display the jobs running on different clusters (Including sub clusters) using PostgreSQL.
My table structure as follows
CREATE TABLE clusterdata(
clusterid bigint NOT NULL,
sourceclustername character varying NOT NULL,
clustername character varying NOT NULL
);
CREATE TABLE job(
clusterid bigint NOT NULL,
jobname character varying NOT NULL,
sourcecluster bigint
);
Please help me...Thanx in advance
Assuming your sentence "1st cluster will have 14 jobs 2nd cluster will have 5 jobs 3rd cluster will have 5 jobs"
you can use something like this:
WITH BASE AS (
SELECT * , ROW_NUMBER() OVER (PARTITION BY sourcecluster, clusterid ORDER BY clusterid, jobname) AS RN
, DENSE_RANK() OVER (PARTITION BY sourcecluster ORDER BY clusterid) * CASE WHEN sourcecluster=0 THEN 0 ELSE 1 END AS RN_GROUP
FROM job )
SELECT A.clusterid AS SOURCE_CLUSTER, A.jobname AS CLUSTER_1
, B.jobname AS CLUSTER_2
, C.jobname AS CLUSTER_3
FROM BASE A
LEFT JOIN BASE B ON B.sourcecluster = A.clusterid AND B.RN_group=1 AND A.RN=B.RN
LEFT JOIN BASE C ON C.sourcecluster = A.clusterid AND C.RN_group=2 AND B.RN=C.RN
WHERE A.sourcecluster=0
ORDER BY A.clusterid, A.RN, B.RN;
Output:
source_cluster cluster_1 cluster_2 cluster_3
1 1 job1 job15 job20
2 1 job2 job16 job21
3 1 job3 job17 job22
4 1 job4 job18 NULL
5 1 job5 NULL NULL
6 4 job41 NULL NULL
7 4 job42 NULL NULL
8 4 job43 NULL NULL
9 4 job44 NULL NULL
10 4 job45 NULL NULL
11 5 job51 job55 NULL
12 5 job52 job56 NULL
13 5 job53 job57 NULL
14 5 job54 job58 NULL
15 5 job55 NULL NULL
Sample data:
INSERT INTO clusterdata VALUES (1, '0', 'clust1');
INSERT INTO clusterdata VALUES (2, 'clust1', 'clust1.1');
INSERT INTO clusterdata VALUES (3, 'clust1', 'clust1.2');
INSERT INTO clusterdata VALUES (4, '0', 'clust2');
INSERT INTO clusterdata VALUES (5, '0', 'clust3');
INSERT INTO clusterdata VALUES (6, 'clust3', 'clust3.1');
INSERT INTO job VALUES (1,'job1',0);
INSERT INTO job VALUES (1,'job2',0);
INSERT INTO job VALUES (1,'job3',0);
INSERT INTO job VALUES (1,'job4',0);
INSERT INTO job VALUES (1,'job5',0);
INSERT INTO job VALUES (2,'job15',1);
INSERT INTO job VALUES (2,'job16',1);
INSERT INTO job VALUES (2,'job17',1);
INSERT INTO job VALUES (2,'job18',1);
INSERT INTO job VALUES (3,'job20',1);
INSERT INTO job VALUES (3,'job21',1);
INSERT INTO job VALUES (3,'job22',1);
INSERT INTO job VALUES (4,'job41',0);
INSERT INTO job VALUES (4,'job42',0);
INSERT INTO job VALUES (4,'job43',0);
INSERT INTO job VALUES (4,'job44',0);
INSERT INTO job VALUES (4,'job45',0);
INSERT INTO job VALUES (5,'job51',0);
INSERT INTO job VALUES (5,'job52',0);
INSERT INTO job VALUES (5,'job53',0);
INSERT INTO job VALUES (5,'job54',0);
INSERT INTO job VALUES (5,'job55',0);
INSERT INTO job VALUES (6,'job55',5);
INSERT INTO job VALUES (6,'job56',5);
INSERT INTO job VALUES (6,'job57',5);
INSERT INTO job VALUES (6,'job58',5);

SQL own sort order

How to sort values (rows with 2 elements) whereby the second colum is the link to the previous row/first column whereby the values are numeric but not sortable on a normal numeric value order/calculated one, example:
1 - 0 no previous row
3 - 1 1 in second colum refers to 1 in previous row in first column
4 - 3 3 in second colum refers to 3 in previous row in first column
2 - 4 ...
9 - 2
7 - 9
5 - 7
6 - 5
8 - 6
sort result should be: 1 - 3 - 4 - 2 - 9 - 7 - 5 - 6 - 8
The tricky part is the unknown sequence, so case, decode, if, ... can't be included because the values are unknown (the only one who is known is the first row by 0 in the second column)
Does someone has already solved such a sortorder?
create table #t (
valor int null
, valor2 int null
, linha int not null identity
)
insert into #t (valor) values (1)
insert into #t (valor) values (3)
insert into #t (valor) values (4)
insert into #t (valor) values (2)
insert into #t (valor) values (9)
insert into #t (valor) values (7)
insert into #t (valor) values (5)
insert into #t (valor) values (6)
insert into #t (valor) values (8)
update #t set #t.valor2 = isnull(t2.valor, 0)
from (
select valor, linha +1 as linha
from #t
) t2
where #t.linha = t2.linha
select valor, valor2, linha from #t order by linha
select valor, isnull(valor2, 0) as valor2 from #t order by 2
drop table #t
The result is something like:

How can I get the expected result in Sybase as below list sql, remove not changed row

create table #test2(
id int identity,
request int null,
step_no int null)
insert into #test2(request) values (12)
insert into #test2(request) values (12)
insert into #test2(request) values (30)
insert into #test2(request) values (30)
insert into #test2(request) values (30)
insert into #test2(request) values (12)
insert into #test2(request) values (24)
insert into #test2(request) values (30)
insert into #test2(request) values (30)
insert into #test2(request) values (24)
Get result:
12
30
12
24
30
24
Try below sql: (I change the table name, so u need to recheck the sql)
select
a.id,
a.request
--, aa.id, aa.request
from #test2 a
left join
(
select c.id,c.request from #test2 c
) aa on a.request = aa.request and a.id = aa.id + 1
where aa.id is null and aa.request is null
Result Table:
id request
----------- -----------
1 12
3 30
6 12
7 24
8 30
10 24

SQL Server field calculation based on multiple condition

Here is my scenario:
I have a Person table with following fields.
create table Person(PersonID int primary key identity(1,1),
Age int,
height decimal(4,2),
weight decimal(6,2)
);
insert into Person(Age,height,weight) values (60,6.2,169); -- 1
insert into Person(Age,height,weight) values (15,5.1,100); -- 2
insert into Person(Age,height,weight) values (10,4.5,50); -- 3
What I need to do is,
if the person Age >= 18 and height >= 6 then calculationValue = 20
if the person Age >= 18 and height < 6 then calculationValue = 15
if the person Age < 18 and weight >= 60 then calculationValue = 10
if the person Age < 18 and weight < 60 then calculationValue = 5
based on these condition I need to find the calculationValue and do some math.
I tried to make a flexible model so in future it would be easier to add any more conditions and can easily change the constant values (like 18, 6, 60 etc)
I created couple of tables as below:
create table condTable(condTableID int primary key identity(1,1),
condCol varchar(20),
startValue int,
endValue int
);
insert into condTable(condCol,startValue,endValue) values ('Age',18,999) -- 1
insert into condTable(condCol,startValue,endValue) values ('Height',6,99) -- 2
insert into condTable(condCol,startValue,endValue) values ('Height',0,5.99) -- 3
insert into condTable(condCol,startValue,endValue) values ('Age',0,17) -- 4
insert into condTable(condCol,startValue,endValue) values ('Weight',60,999) -- 5
insert into condTable(condCol,startValue,endValue) values ('Weight',0,59) -- 6
I join two condition to make it one in the following table as given by the requirement.(ie. if age >=18 and height >=6 then calculationValue = 20. etc)
create table CondJoin(CondJoin int,condTableID int,CalculationValue int)
insert into CondJoin values (1,1,20)
insert into CondJoin values (1,2,20)
insert into CondJoin values (2,1,15)
insert into CondJoin values (2,3,15)
insert into CondJoin values (3,4,10)
insert into CondJoin values (3,5,10)
insert into CondJoin values (4,4,5)
insert into CondJoin values (4,6,5)
I think this model will provide the flexibility of adding more conditions in future. But I am having difficulties on implementing it in SQL Server 2005. Anyone can write a sql that process in set basis and compare the value in Person table with CondJoin table and provide the corresponding calculationvalue. For eg. for person ID 1 it should look at CondJoin table and give the calculationValue 20 since his age is greater than 18 and height is greater than 6.
this looks like you are headed towards dynamic sql generation.
i think maybe you would be better off with a row for each column and cutoff values for the ranges, and a value if true ... maybe something like:
age_condition
-----------------
min_age
max_age
value
this is something that you could populate and then query without some dynamic generation.
The following is extremely rough but it should get the point across. It normalizes the data and moves towards a semi-object oriented (attribute/value/attribute value) structure. I'll leave it up to you to reinforce referential integrity, but the following is flexible and will return the results you want:
CREATE TABLE Person (
PersonID INT PRIMARY KEY IDENTITY(1,1)
,Name NVARCHAR(255)
);
GO
CREATE TABLE PersonAttribute (
PersonID INT
,CondAttributeID INT
,Value NVARCHAR(255)
);
GO
CREATE TABLE CondAttribute (
AttributeID INT PRIMARY KEY IDENTITY(1,1)
,Attribute NVARCHAR(255));
GO
CREATE TABLE CondTable (
CondTableID INT PRIMARY KEY IDENTITY(1,1)
,CondAttributeID INT
,StartValue MONEY
,EndValue MONEY
);
GO
CREATE TABLE CalculationValues (
CalculationID INT PRIMARY KEY IDENTITY(1,1)
,CalculationValue INT
);
GO
CREATE TABLE CondCalculation (
CondTableID INT
,CalculationID INT
);
INSERT Person (Name)
VALUES ('Joe')
,('Bob')
,('Tom');
INSERT PersonAttribute (
PersonID
,CondAttributeID
,Value
)
VALUES (1, 1, '60')
,(1, 2, '6.2')
,(1, 3, '169')
,(2, 1, '15')
,(2, 2, '5.1')
,(2, 3, '100')
,(3, 1, '10')
,(3, 2, '4.5')
,(3, 3, '50');
INSERT CondAttribute (Attribute)
VALUES ('Age')
,('height')
,('weight');
INSERT CondTable (
CondAttributeID
,StartValue
,EndValue)
VALUES (1,18,999) --Age
,(2,6,99) --Height
,(2,0,5.99) -- Height
,(1,0,17) -- Age
,(3,60,999) -- Weight
,(3,0,59); -- Weight
INSERT CalculationValues (CalculationValue)
VALUES (5)
,(10)
,(15)
,(20);
INSERT CondCalculation (CondTableID, CalculationID)
VALUES (1,4)
,(2,4)
,(1,3)
,(3,3)
,(4,2)
,(5,2)
,(5,1)
,(6,1);
SELECT *
FROM Person AS p
JOIN PersonAttribute AS pa ON p.PersonID = pa.PersonID
JOIN CondAttribute AS ca ON pa.CondAttributeID = ca.AttributeID
JOIN CondTable AS ct ON ca.AttributeID = ct.CondAttributeID
AND CONVERT(money,pa.Value) BETWEEN ct.StartValue AND ct.EndValue
JOIN CondCalculation AS cc ON cc.CondTableID = ct.CondTableID
JOIN CalculationValues AS c ON cc.CalculationID = c.CalculationID
WHERE p.PersonID = 1
The following solution uses PIVOT (twice) to transform the combination of CondJoin and condTable into a chart, then joins the chart to the Person table to calculate the target value. I believe, a series of CASE expressions could be used instead just as well. Anyway...
All the tables have been turned into table variables, for easier testing. So first, DDL and data preparation:
declare #Person table(PersonID int primary key identity(1,1),
Age int,
height decimal(4,2),
weight decimal(6,2)
);
insert into #Person(Age,height,weight) values (60,6.2,169); -- 1
insert into #Person(Age,height,weight) values (15,5.1,100); -- 2
insert into #Person(Age,height,weight) values (10,4.5,50); -- 3
declare #condTable table(condTableID int primary key identity(1,1),
condCol varchar(20),
startValue int,
endValue int
);
insert into #condTable(condCol,startValue,endValue) values ('Age',18,999) -- 1
insert into #condTable(condCol,startValue,endValue) values ('Height',6,99) -- 2
insert into #condTable(condCol,startValue,endValue) values ('Height',0,5.99) -- 3
insert into #condTable(condCol,startValue,endValue) values ('Age',0,17) -- 4
insert into #condTable(condCol,startValue,endValue) values ('Weight',60,999) -- 5
insert into #condTable(condCol,startValue,endValue) values ('Weight',0,59) -- 6
declare #CondJoin table(CondJoin int,condTableID int,CalculationValue int);
insert into #CondJoin values (1,1,20)
insert into #CondJoin values (1,2,20)
insert into #CondJoin values (2,1,15)
insert into #CondJoin values (2,3,15)
insert into #CondJoin values (3,4,10)
insert into #CondJoin values (3,5,10)
insert into #CondJoin values (4,4,5)
insert into #CondJoin values (4,6,5)
And now the query:
;with startValues as (
select
CondJoin,
Age,
Height,
Weight,
CalculationValue
from (
select
j.CondJoin,
j.CalculationValue,
t.condCol,
t.startValue
from #CondJoin j
inner join #condTable t on j.condTableID = t.condTableID
) j
pivot (
max(startValue) for condCol in (Age, Height, Weight)
) p
),
endValues as (
select
CondJoin,
Age,
Height,
Weight,
CalculationValue
from (
select
j.CondJoin,
j.CalculationValue,
t.condCol,
t.endValue
from #CondJoin j
inner join #condTable t on j.condTableID = t.condTableID
) j
pivot (
max(endValue) for condCol in (Age, Height, Weight)
) p
),
combinedChart as (
select
s.CondJoin,
AgeFrom = s.Age,
AgeTo = e.Age,
HeightFrom = s.Height,
HeightTo = e.Height,
WeightFrom = s.Weight,
WeightTo = e.Weight,
s.CalculationValue
from startValues s
inner join endValues e on s.CondJoin = e.CondJoin
)
select
p.*,
c.CalculationValue
from #Person p
left join combinedChart c
on (c.AgeFrom is null or p.Age between c.AgeFrom and c.AgeTo)
and (c.HeightFrom is null or p.Height between c.HeightFrom and c.HeightTo)
and (c.WeightFrom is null or p.Weight between c.WeightFrom and c.WeightTo)