SQL own sort order - sql

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:

Related

Creating a time table using 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;

SQL Subtract the values of two resultsets

Is there an operator eavailable similar to UNION that will allow one query's resultset to be subtracted from another?
eg:
Result of a UNION
2 3 2 6 1 2 6 3 7
1 3 5 2 7 8 4 3 2
Result of potential subtraction operator
1 0 -3 4 -6 -6 2 0 5
You case is much simpler: just subtract one column from another
CREATE TABLE #A
(
col1 INT NOT NULL
,col2 INT NOT NULL
);
INSERT INTO #A (col1,col2)
VALUES
(2,1)
,(3,3)
,(2,5)
,(6,2)
,(1,7)
,(2,8)
,(6,4)
,(3,3)
,(7,2)
SELECT (col1 - col2) AS result
FROM #A;
DROP TABLE #A;
Original answer
So if I understand you correctly you need to Subtract two one dimensional matrixes. Sql Server is not really the best tool to do such a math, but here is the example how you can achieve your goal. The idea is simple: introduce indexes (i,j) and join by them (you can skip j since you matrix is one-dimensional, the example works for two-dimensional arrays):
CREATE TABLE #A
(
element_value INT NOT NULL
,i INT NOT NULL
,j INT NOT NULL
,PRIMARY KEY (i, j)
);
CREATE TABLE #B
(
element_value INT NOT NULL
,i INT NOT NULL
,j INT NOT NULL
,PRIMARY KEY (i, j)
);
INSERT INTO #A (element_value,i,j)
VALUES
(2,1,1)
,(3,1,2)
,(2,1,3)
,(6,1,4)
,(1,1,5)
,(2,1,6)
,(6,1,7)
,(3,1,8)
,(7,1,9)
INSERT INTO #B (element_value,i,j)
VALUES
(1,1,1)
,(3,1,2)
,(5,1,3)
,(2,1,4)
,(7,1,5)
,(8,1,6)
,(4,1,7)
,(3,1,8)
,(2,1,9)
SELECT (A.element_value - B.element_value) AS result
FROM #A AS A,#B AS B
WHERE A.i = B.i
AND A.j = B.j;
DROP TABLE #A;
DROP TABLE #B;

Adding total row and Increasing quality for an sql query based on multiple parameters

I have a table in Microsoft Sql Server 2008 like:
id name timelong
1 Eray 2
1 Jack 1
1 Ali 7
1 john 3
1 Roby 5
1 Mike 4
1 Josh 11
What I want to do is to select data based on user multi-selectable parameters. Think that there are 4 checkboxes: 0-3,4-6,7-9,10-12 and users can select more than one checkbox. Only those data user selected should be seen and a TOTAL row needs to be added at the bottom.
What I tried is on the bottom but it is not working well - TOTAL row is not there. My question is how I can add the Total row there, and is there any more professional way to provide this query. Thanks.
declare #interval03 bit -- 0 to 3
declare #interval06 bit -- 4 to 6
declare #interval09 bit -- 7 to 9
declare #interval12 bit -- 10 to 12
Select *, sum(timelong)
From myTable
Where (#interval03=1 and timelong<4)
or
(#interval06=1 and timelong>3 and timelong<7)
or
(#interval09=1 and timelong>6 and timelong<10)
or
(#interval12=1 and timelong>9 and timelong<13)
group by id, name
Try grouping sets:
Select ID, isnull(Name, 'TOTAL'), sum(timelong)
From myTable
Where (#interval03=1 and timelong <= 3)
or
(#interval06=1 and timelong between 4 and 6)
or
(#interval09=1 and timelong between 7 and 9)
or
(#interval12=1 and timelong >= 10)
group by grouping sets ((ID, name), ())
Assuming from your query that timelong is an int, I've simplified your where a little as well.
More information on grouping sets, rollup, and cube: https://technet.microsoft.com/en-us/library/bb522495(v=sql.105).aspx
TRY This..One more way to add totals...
declare #table Table (id INT,name VARCHAR(10), timelong INT)
insert into #table (id ,name, timelong) VALUES (1, 'Eray', 2)
insert into #table (id ,name, timelong) VALUES (1 ,'Jack' ,1)
insert into #table (id ,name, timelong) VALUES (1 ,'Ali' , 7)
insert into #table (id ,name, timelong) VALUES (1 ,'john' ,3)
insert into #table (id ,name, timelong) VALUES (1 ,'Roby' , 5)
insert into #table (id ,name, timelong) VALUES (1 ,'Mike' ,4)
insert into #table (id ,name, timelong) VALUES (1 ,'Josh' ,11)
declare #interval03 bit=1 -- 0 to 3
declare #interval06 bit -- 4 to 6
declare #interval09 bit -- 7 to 9
declare #interval12 bit -- 10 to 12
DECLARE #result TABLE (ID INT,Name VARCHAR (30),TimeLong INT)
INSERT INTO #result
Select id, name, sum(timelong) timelong
From #table
Where (#interval03=1 and timelong<4)
or (#interval06=1 and timelong>3 and timelong<7)
or (#interval09=1 and timelong>6 and timelong<10)
or (#interval12=1 and timelong>9 and timelong<13)
group by id, name
INSERT INTO #result
SELECT MAX(ID) +100 ID,'Total' Name,SUM(TimeLong) TimeLong
FROM #result
HAVING COUNT(*)<>0
SELECT * FROM #result

T/SQL - Semi-manual Identity Column Insertion

Initial Query
DECLARE #Table1 TABLE (ID int, Value varchar(50))
DECLARE #Table2 TABLE (Value varchar(50))
DECLARE #MaxID1 int
DECLARE #MaxID2 int = 52
INSERT INTO #Table1 (ID, Value)
Values (1,'One'),(2,'Two'),(3,'Three'),(4,'Four'),(5,'Five')
INSERT INTO #Table2 (Value)
Values ('Six'),('Seven'),('Eight'),('Nine'),('Ten')
SELECT * FROM #Table1
SELECT * FROM #Table2
SELECT #MaxID1 = MAX(ID) FROM #Table1
SELECT #MaxID1 Scenario1, #MaxID2 Scenario2
Expected Outcome of #Table1 after inserting values (Value field) from #Table2
// (Scenario #1 using #MaxID1)
ID Value
1 One
2 Two
3 Three
4 Four
5 Five
6 Six
7 Seven
8 Eight
9 Nine
10 Ten
// (Scenario #2 using #MaxID2)
ID Value
1 One
2 Two
3 Three
4 Four
5 Five
52 Six
53 Seven
54 Eight
55 Nine
56 Ten
How do I semi-manually insert ID values into an Identity column (ID) while executing INSERT query on that table (#Table1) from another table (#Table2)? In the first scenario, I wish to take the Max(ID) from #Table1 and add 1 to it and keep adding records. In the second scenario, I wish to take a predefined # and then start adding a record where first new record's ID would be the predefined values and all subsequent new records would be Max(ID) + 1.
Thank you
UPDATED #Table 1 does NOT have identity constraint.
If you want to insert an arbitrary int value into an identity column, use IDENTITY_INSERT:
SET IDENTITY_INSERT [table_name] ON;
Only one table at a time for a given session can have this property on. Make sure you turn it off when done:
SET IDENTITY_INSERT [table_name] OFF;

Random Function behavior in SELECT query in SQL Server

I have a written a random function dbo.UDF_Q_RandomNumber() that generates a floating type random number between 0 and 1.
DECLARE #upper = 10
DECLARE #lower = 1
SELECT
ROUND(CAST((#lower + (#upper - #lower) * dbo.UDF_Q_RandomNumber()) AS INT), 0)
The above code generates a random number between 1 and 10.
Now I created a temporary table #tempTable with 10 rows in it with columns Id and Number.
Id Number
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
SQL query:
CREATE TABLE #tempTable(Id INT, Number INT)
INSERT INTO #tempTable VALUES (1,1)
INSERT INTO #tempTable VALUES (2,2)
INSERT INTO #tempTable VALUES (3,3)
INSERT INTO #tempTable VALUES (4,4)
INSERT INTO #tempTable VALUES (5,5)
INSERT INTO #tempTable VALUES (6,6)
INSERT INTO #tempTable VALUES (7,7)
INSERT INTO #tempTable VALUES (8,8)
INSERT INTO #tempTable VALUES (9,9)
INSERT INTO #tempTable VALUES (10,10)
DECLARE #maxCount INT;
SELECT #maxCount= COUNT(1) FROM #tempTable
SELECT * FROM #tempTable
SELECT Number
FROM #tempTable
WHERE Id = ROUND(CAST((1+(#maxCount-1)*dbo.UDF_Q_RandomNumber())AS INT),0)
DROP TABLE #tempTable
Here the query
SELECT Number
FROM #tempTable
WHERE Id = ROUND(CAST((1+(#maxCount-1)*dbo.UDF_Q_RandomNumber()) AS INT), 0)
Sometimes it returns 2 rows and sometimes null which should not come as Id selected is between 1 and 10 (the rows in temptable) and every Id has value too.
Please help .
Without seeing the function, it's hard to say, but I suspect your function is non-deterministic, so it gets interpreted for each row of the table.
If you use rand() it only returns one row
SELECT Number FROM #tempTable WHERE Id= ROUND(CAST((1+(#maxCount-1)*rand())AS INT),0)
Alternatively, if you just want a random #n rows...
select top (#n) * from #tempTable order by newid()