Create SQL Function view with User ID and Date range - sql

As I title says, I need to create a Function View of two tables.
Below are the SQL Tables
CREATE TABLE User_Specialist(
ID_User_Specialist INT NOT NULL,
Name_User_Specialist VARCHAR(50) NOT NULL,
CONSTRAINT PK_ID_User_Specialist PRIMARY KEY(ID_User_Specialist),
GO
CREATE TABLE Incident(
ID_Incident INT IDENTITY(1,1) NOT NULL,
Incident_Creation_Date DATETIME NULL,
Assigned_Specialist INT NULL,
CONSTRAINT FK_Assigned_Specialist FOREIGN KEY (Especialista_Asignado) REFERENCES Usuario_Especialista(ID_Usuario_Especialista),
GO
Based on the previous information, I need the function to display Assign Specialist and the dates that the Incident was created.
Right know this is what I got:
CREATE FUNCTION View_Date (#ID_User_Incident INT)
RETURNS INT
AS
BEGIN
DECLARE #Total_Incidents INT
SELECT #Total_Incidents = COUNT(ID_Incident)
FROM Incidents i, User_Specialist u
WHERE i.ID_Incident = u.ID_User_Specialist AND u.ID_User_Specialist =#ID_User_Incident
RETURN (#Total_Incidents)
END
GO
DECLARE #Specialist_ID int;
EXEC #Specialist_ID = [dbo].View_Date
#ID_Incidentes_Usuarios = 5;
SELECT #Specialist_ID AS 'Assigned Specialist Incidents'
GO
The only thing missing is the dates range.

I believe you changed your table and field names to English from Spanish. You have missed some of them and there were some missing parenthesis. As much as I understand I changed them to understand better.
CREATE TABLE User_Specialist
(
ID_User_Specialist INT NOT NULL,
Name_User_Specialist VARCHAR(50) NOT NULL
CONSTRAINT PK_ID_User_Specialist PRIMARY KEY(ID_User_Specialist)
)
GO
CREATE TABLE Incident
(
ID_Incident INT IDENTITY(1,1) NOT NULL,
Incident_Creation_Date DATETIME NULL,
Assigned_Specialist INT NULL
CONSTRAINT FK_Assigned_Specialist FOREIGN KEY (Assigned_Specialist) REFERENCES User_Specialist(ID_User_Specialist)
)
GO
If you want to see multiple columns or rows as result you need to use Table-valued Function. I have created sample query from your table and prepared function. you can change it with what you want.
CREATE FUNCTION dbo.FN_ViewDate
(
#ID_User_Incident INT
)
RETURNS #Result TABLE
(
TotalIncidents INT
,FirstIncidentDate DATETIME
,LastIncidentDate DATETIME
)
AS
BEGIN
INSERT INTO #Result
SELECT COUNT(ID_Incident)
,MIN(Incident_Creation_Date)
,MAX(Incident_Creation_Date)
FROM Incident I
LEFT JOIN User_Specialist U ON I.Assigned_Specialist = U.ID_User_Specialist
WHERE I.Assigned_Specialist = #ID_User_Incident
RETURN
END
GO

I think this query can help you.
declare #count int = 0 , #dates varchar(200) =''
SELECT #count+=1 , #dates +=' '+ i.Incident_Creation_Date
FROM Incidents i, User_Specialist u
WHERE i.ID_Incident = u.ID_User_Specialist AND u.ID_User_Specialist =#ID_User_Incident
select #count as [count] ,#dates [incidentDates]

Related

How to move hierarchyid subtree if the new parent has already got children?

I guess the problem is described in the title pretty well. I've got a table like this:
CREATE TABLE [Employees] (
[Id] INT identity(1, 1) PRIMARY KEY
,[Hid] HIERARCHYID NOT NULL
,[Name] VARCHAR(50) NULL
,[Secondname] VARCHAR(50)
,[Surname] VARCHAR(50)
,[BossId] INT FOREIGN KEY REFERENCES [Employees]([Id])
,[PositionId] INT FOREIGN KEY REFERENCES [Positions]([Id])
,[DepartmentId] INT FOREIGN KEY REFERENCES [Departments]([Id])
,[RecruitDate] DATE NOT NULL
);
And I need to change employee's boss from one to another. Obviously, there is a nice solution - GetReparentedValue(), and I used this example that seemed to be exactly what I needed.
But this solution happens to be not working. Hid.GetAncestor(1) is equal to previous BossHid. Probably, the problem is that it can't work well if new parent already got children. That really upsets me. Does it mean I need to write recursive CTE on my own?
Here is the code that was supposed to be working but it didn't:
CREATE PROCEDURE UpdateEmployee #Id INT
,#Name VARCHAR(50)
,#Secondname VARCHAR(50)
,#Surname VARCHAR(50)
,#BossId INT
,#PosId INT
,#DepId INT
,#Rdate DATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #BossExist INT
,#OldBossHid HIERARCHYID
,#NewBossHid HIERARCHYID
,#LastHid HIERARCHYID;
SELECT #BossExist = count(*)
FROM dbo.Employees
WHERE [Hid] = HIERARCHYID::GetRoot();
IF #BossExist != 0
AND #BossId IS NULL
RETURN;
SELECT #OldBossHid = (
SELECT [Hid].GetAncestor(1)
FROM dbo.Employees
WHERE #Id = [Id]
);
SELECT #NewBossHid = (
SELECT [Hid].GetAncestor(1)
FROM dbo.Employees
WHERE #BossId = BossId
);
SELECT #LastHid = #NewBossHid.GetDescendant(MAX([Hid]), NULL)
FROM dbo.Employees
WHERE [Hid].GetAncestor(1) = #NewBossHid;
UPDATE dbo.Employees
SET [Hid] = [Hid].GetReparentedValue(#OldBossHid, #NewBossHid)
WHERE [Hid].IsDescendantOf(#OldBossHid) = 1;
UPDATE dbo.Employees
SET [Name] = #Name
,[Secondname] = #Secondname
,[Surname] = #Surname
,[BossId] = #BossId
,[PositionId] = #PosId
,[DepartmentId] = #DepId
,[RecruitDate] = #Rdate
WHERE #Id = Id;
END
GO
Thank you.

How to use stored procedure to add mutiple locations to one customer?

I have trouble on how to use stored procedure to add multiple locations to one customer. Below are my tables, I am using indexing to help me can add multiple locations to one customer, but should I
SELECT #intLocationIndex = MAX(intLocationIndex) +1
too?
CREATE TABLE TCustomer
(
intCustomerID INTEGER NOT NULL,
strCustomerName VARCHAR(50) NOT NULL,
strAddress VARCHAR(50) NOT NULL,
CONSTRAINT TCustomer_PK PRIMARY KEY (intCustomerID)
)
CREATE TABLE TCustomerLocation
(
intLocationID INTEGER NOT NULL,
intLocationIndex INTEGER NOT NULL,
intCustomerID INTEGER NOT NULL,
CONSTRAINT TCustomerLocation_PK
PRIMARY KEY(intLocationID, intLocationIndex)
)
CREATE TABLE TLocation
(
intLocationID INTEGER NOT NULL,
strLocationName VARCHAR(50) NOT NULL,
strLocationAddress VARCHAR(50) NOT NULL,
strLocationCity VARCHAR(50) NOT NULL,
CONSTRAINT TLocation_PK PRIMARY KEY(intLocationID)
)
CREATE PROCEDURE uspAddCustomerLocation
#strCustomerName VARCHAR(50),
#strAddress VARCHAR(50),
#strLocationName VARCHAR(50),
#strLocationAddress VARCHAR(50),
#strLocationCity VARCHAR(50)
AS
BEGIN TRANSACTION
SET XACT_ABORT ON
DECLARE #intCustomerID INTEGER
SELECT #intCustomerID = MAX(intCustomerID) + 1
FROM TCustomer (TABLOCKX) -- LOCK TABLE UNTIL THE END OF TRANSACTION
SELECT #intCustomerID = COALESCE( #intCustomerID , 1)
INSERT INTO TCustomer (intCustomerID, strCustomerName , strAddress)
VALUES(#intCustomerID ,#strCustomerName ,#strAddress)
DECLARE #intLocationID INTEGER
DECLARE #intLocationIndex INTEGER
SELECT #intLocationID = MAX(intLocationID) + 1
FROM TLocation (TABLOCKX) -- LOCK TABLE UNTIL THEEND OF TRANSACTION
COMMIT TRANSACTION
GO
I am not a DBA but I wish these ID fields were IDENTITY fields. Anyway I think the select in question would be SELECT #intLocationIndex = MAX(intLocationIndex) +1 Where intCustomerID = #intCustomerID

How to use parameters in select query?

I have table :
Table Name : tbl_Income
EmployeeID Element FinancialYear Jan Feb Mar
00402060 Basic 2016-2017 100 200 300
00402060 HRA 2016-2017 100 200 300
00402060 DA 2016-2017 100 200 300
In which i want to fetch data from tbl_Income.
In which i fetch below problem.
Declare #Month varchar(10) = 'Jan'
select #Month from tbl_Income where EmployeeID = '00402060' and Element = 'Basic' and FinancialYear = '2016-2017'
I want to below Output
OUTPUT :
Jan
1 100
Please help me...
You can use Dynamic SQL like this:
declare #sql nvarchar(max)
Declare #Month varchar(10) = 'Jan'
declare #income int
set #sql = 'select #inc=' + #Month + ' from tbl_Income where EmployeeID = ''00402060'' and Element = ''Basic'' and FinancialYear = ''2016-2017'''
exec sp_executesql #sql, N'#inc int OUTPUT', #inc=#income OUTPUT
select #income as income
Beware though that this is open to SQL Injection attack.
You'd be better off fixing your design.
[Sample Database Design][1]
[1]: https://i.stack.imgur.com/2vxEb.png
-- table "dbo.Month"
CREATE TABLE dbo.Month (
Id int NOT NULL,
Name nvarchar(50) NOT NULL,
CONSTRAINT PK_Month PRIMARY KEY CLUSTERED (Id)
)
-- table IncomeType"
CREATE TABLE dbo.IncomeType (
Id int NOT NULL,
Name nvarchar(50) NOT NULL,
CONSTRAINT PK_IncomeType PRIMARY KEY CLUSTERED (Id)
)
-- table "FinancialYear"
CREATE TABLE dbo.FinancialYear (
Id int NOT NULL,
YearSpan nvarchar(50) NOT NULL,
CONSTRAINT PK_FinancialYear PRIMARY KEY CLUSTERED (Id)
)
-- table "Employee"
CREATE TABLE dbo.Employee (
Id int NOT NULL,
Name nvarchar(50) NOT NULL,
CONSTRAINT PK_Employee PRIMARY KEY CLUSTERED (Id)
)
-- table "Income"
CREATE TABLE dbo.Income (
Id int NOT NULL,
EmployeeId int NOT NULL,
TypeId int NOT NULL,
YearSpanId int NOT NULL,
MonthId int NOT NULL,
CONSTRAINT PK_Income PRIMARY KEY CLUSTERED (Id)
)
--Alter Each Table to add foreign key references
ALTER TABLE Income
ADD CONSTRAINT FK_Income_Employee FOREIGN KEY (EmployeeId) REFERENCES Employee (Id)
ALTER TABLE dbo.Income
ADD CONSTRAINT FK_Income_FinancialYear FOREIGN KEY (YearSpanId) REFERENCES dbo.FinancialYear (Id)
ALTER TABLE dbo.Income
ADD CONSTRAINT FK_Income_IncomeType FOREIGN KEY (TypeId) REFERENCES dbo.IncomeType (Id)
ALTER TABLE dbo.Income
ADD CONSTRAINT FK_Income_Month FOREIGN KEY (MonthId) REFERENCES dbo.Month (Id)
EmployeeID will come from the Employee table
Element will come from the income type table
FinancialYear --from the financial year table
MonthId from the months table
Now a simple join can help you get each value using the foreign key references
Declare #Month varchar(10) = 'Jan'
declare #v nvarchar(max)
declare #v1 INT
set #v =CONCAT('select #v1=' ,#month, ' from
table_a where EmployeeID = ''00402060'' and Element = ''Basic'' and FinancialYear = ''2016-2017''')
PRINT #V
EXECUTE sp_executesql #v,N'#V1 INT OUTPUT', #V1=#V1 OUTPUT;
SELECT #V1;

SQL How to convert this to a SubQuery?

Learning, be kind.
I am trying to understand how this works and I have done several successful conversions, but this one I am stumped on.
How do I take this code and convert it to a subquery? I'm a little lost.
SELECT o.FirstName + ' ' + o.LastName AS Driver, COUNT(DISTINCT s.vehicleID) NoOfBusesUsed
FROM Operators AS o, Runs AS r, Schedules AS s JOIN Trips AS t
ON s.scheduleID = t.scheduleID
WHERE r.BidDate BETWEEN '09/01/2004' AND '09/30/2004'
GROUP BY o.FirstName + ' ' + o.LastName
HAVING COUNT(s.vehicleID) > 1
Here is how my tables are setup. If more info is needed, I can post.
CREATE TABLE Operators
(
SeniorityNumber char(4) NOT NULL
CONSTRAINT ck_Operators_Seniority
CHECK (SeniorityNumber LIKE '[0-9][0-9][0-9][0-9]'),
FirstName varchar(25) NOT NULL,
LastName varchar(35) NOT NULL,
HireDate smalldatetime
CONSTRAINT ck_Operators_HireDate CHECK (HireDate <=Getdate())
)
CREATE TABLE Trips
(
RouteNumber varchar(4) NOT NULL,
StartLocation varchar(50) NOT NULL,
StartTime time NOT NULL,
EndLocation varchar(50) NOT NULL,
EndTime time NOT NULL,
EffectiveDate smalldatetime NOT NULL
CHECK (EffectiveDate >= cast('1/1/2000' as smalldatetime)),
CONSTRAINT ck_Trips_StartEnd CHECK (EndTime > StartTime)
)
CREATE TABLE Vehicles
(
Manufacturer varchar(50)
DEFAULT 'Gillig',
Model varchar(50),
ModelYear int
DEFAULT DatePart(yyyy,GetDate())
CHECK (ModelYear <= DatePart(yyyy,GetDate())),
PurchaseDate smalldatetime
)
GO
ALTER TABLE operators
ADD OperatorID int IDENTITY --Primary Key
GO
ALTER TABLE Operators
ADD CONSTRAINT pkOperators Primary key (OperatorID)
ALTER TABLE Vehicles
ADD VehicleID int IDENTITY Primary Key
ALTER TABLE Trips
ADD TripID int IDENTITY Primary key
GO
CREATE TABLE Runs
(
RunID int IDENTITY NOT NULL Primary Key,
OperatorID int NOT NULL REFERENCES Operators,
BidDate date NOT NULL
CONSTRAINT ckRunBidDate CHECK
(biddate <= dateadd(mm,6,getdate())) --getdate() + 180
)
GO
CREATE TABLE Schedules
(
ScheduleID int IDENTITY Primary Key,
RunID int NOT NULL,
VehicleID int NOT NULL,
CONSTRAINT fk_Schedules_Runs FOREIGN KEY (RunID)
REFERENCES Runs(RunID),
CONSTRAINT fk_Schedules_Vehicles FOREIGN KEY (VehicleID)
REFERENCES Vehicles
)
ALTER TABLE Trips
ADD ScheduleID int NULL REFERENCES Schedules
When you want to use a query as a sub-query you can use WITH statement or a derived table like:
With:
;WITH subQuery AS (
/* Your query here */
)
SELECT *
FROM subQuery
Derived table
SELECT *
FROM (
/* your query here */
) As subQuery
I think you should use a query like this:
SELECT
o.FirstName + ' ' + o.LastName AS Driver,
DT.cnt AS NoOfBusesUsed
FROM
Operators AS o
JOIN
(SELECT
r.OperatorID,
COUNT(DISTINCT s.VehicleID) AS cnt
FROM
Schedules s
JOIN
Runs r ON s.RunID = r.RunID
) AS DT
ON DT.OperatorID = o.OperatorID
WHERE
ISNULL(DT.cnt, 0) > 1

What's the query needed to copy data from one table to another two?

I recently changed my database structure and now I want to copy from my old table Transfers to the new ones I just created (Orders and Orders_Transfer):
--old table to copy from
-- table 'Transfers'
CREATE TABLE [dbo].[Transfers] (
[Id] int IDENTITY(1,1) NOT NULL,
[Date] datetime NOT NULL,
[Memo] nvarchar(max) NULL,
[Employee_Id] int NULL,
[InventoryFrom_Id] int NOT NULL,
[InventoryTo_Id] int NOT NULL,
);
-- new tables to copy to
-- table 'Orders'
CREATE TABLE [dbo].[Orders] (
[Id] int IDENTITY(1,1) NOT NULL,
[Date] datetime NOT NULL,
[Memo] nvarchar(max) NULL,
[Employee_Id] int NULL
);
-- Creating table 'Orders_Transfer'
CREATE TABLE [dbo].[Orders_Transfer] (
[Id] int NOT NULL,--foreign key on Orders.Id
[InventoryFrom_Id] int NOT NULL,
[InventoryTo_Id] int NOT NULL
);
I want to iterate through the old Transfers table and copy some part of it to Orders (Date, Memo, Employee) and the rest to Orders_Transfer (InventoryFrom_Id, InventoryTo_Id). The Id column in Orders_Transfer is also a FK on Orders.Id so I want to copy the auto-generated value as well.
I read about the scope_identity() function and the OUTPUT clause, but I’m a beginner to SQL and can’t put it all together.
I’m using SQL Server 2008
What is the query I need to do this? Any help would be appreciated, thanks!
I would create an OldId column on the Orders table to store the old primary key:
ALTER TABLE [dbo].[Orders] ADD [OldId] INT;
Then copy in the old data:
INSERT INTO [dbo].[Orders]
(
[OldId],[Date],[Memo],[EmployeeID]
)
SELECT [Id] AS [OldId],[Date],[Memo],[EmployeeID]
FROM [dbo].[Transfers];
Copy the remaining data using the OldId:
INSERT INTO [dbo].[Orders_Transfer]
(
[Id],
[InventoryFrom_Id],
[InventoryTo_Id]
)
SELECT
O.Id, T.[InventoryFrom_Id], T.[InventoryTo_Id]
FROM [dbo].[Orders] O
INNER JOIN [dbo].[Transfers] T
ON O.[OldId] = T.[Id];
And drop the OldId column:
ALTER TABLE [dbo].[Orders] DROP COLUMN [OldId];
To keep the Id values in sync you are going to need to use IDENTITY_INSERT.
SET IDENTITY_INSERT dbo.Orders ON;
/* Insert data into the Orders table */
INSERT INTO [dbo].[Orders]
([Id]
,[Date]
,[Memo]
,[Employee_Id])
SELECT Id
, Date
, Memo
, Employee_Id
FROM Transfers;
SET IDENTITY_INSERT dbo.Orders OFF;
/* Insert data into the Orders_Transfer table */
INSERT INTO [dbo].[Ordres_Transfer]
([Id]
,[InventoryFrom_ID]
,[InventoryTo_ID]
SELECT Id
, InventoryFrom_ID
, InentoryTo_ID
FROM Transfers;
Insert into newtable select * from oldtable //if same schema
insert into newtable(col1,col2,col3) select col1,col2,col3 from old table // for different table schema