TSQL - Updating column based on bit column - sql-server

I have an identity column in my table [ID]. I also have a computed column that is based on the identity column like so;
create table [dbo].[tblMaster] (
ID bigint identity(1,1),
GlobalFamilyUniqueID int,
DupeIdentifier as cast('EDME' + RIGHT('00000000'+ISNULL(cast([ID] as nvarchar(max)),''),8) as nvarchar(30)),
ControlNumber nvarchar(30),
NuixGuid nvarchar(50),
TopLvlGuid nvarchar(50),
ParentGuid nvarchar(50),
CustodianArtifactID int,
IsGlobalFamilyUnique int,
IsCustodianFamilyUnique int,
IsItemUnique int,
ItemUniqueDupID nvarchar(100),
IsChild int,
GroupIdentifier nvarchar(100),
DatasourceID int,
MD5Hash nvarchar(32),
GlobalFamilyDupID nvarchar(100),
CustodianFamilyDupId nvarchar(100),
ExportSessionID nvarchar(100)
)
I want to be update the ControlNumber column based on the IsGlobalFamilyUnique column. At the minute, DupeIdentifier will have a value regardless if IsGlobalFamilUnique is 1 or 0. I need ControlNumber to have an incremental value based on the last value in the ControlNumber field (I created another column called GlobalFamilyUnqiueID as a "counter" column) , but only when IsGlobalFamilUnique is 1.
This is where I am at so far;
update x
set
GlobalFamilyUniqueID = [ProposedGlobalFamilyUniqueID],
ControlNumber = [ProposedControlNumber]
from(
Select top 10 [id],
DupeIdentifier,
-- ControlNumber,
isglobalfamilyunique,
--GlobalFamilyUniqueID,
GlobalFamilyUniqueID,
Row_Number() Over(Order By [id]) [ProposedGlobalFamilyUniqueID],
ControlNumber,
'TEST' + RIGHT('00000000'+ISNULL(cast(Row_Number() Over(Order By [id]) as nvarchar(30)),''),8) [ProposedControlNumber]
From dbo.tblMaster mstr1
where IsGlobalFamilyUnique = 1 and ControlNumber is null
)x
The problem is that when the code is run again ProposedGlobalFamilyUniqueID will start at 1 again. It should start at the last value of ProposedGlobalFamilyUniqueID in dbo.tblMaster. I assume this is because I am limiting the query to where ControlNumber is null, but I don't know how to get around this.
This is an example of the code working successfully the first time its run:
The end result should be sequential ControlNumber values where IsGlobalFamilyUnique = 1
Example Data
declare #test table (
ID bigint identity(1,1),
GlobalFamilyUniqueID int,
DupeIdentifier as cast('EDME' + RIGHT('00000000'+ISNULL(cast([ID] as nvarchar(max)),''),8) as nvarchar(30)),
ControlNumber nvarchar(30),
MD5Hash nvarchar(32),
IsGlobalFamilyUnique bit
)
insert into #test (MD5Hash, IsGlobalFamilyUnique)values
--1
('ABC', 1),
--2
('DEF', 1),
--3
('GHI', 1),
--4
('JKL', 1),
--5
('ABC', 0),
--6
('XXX', 1)
The result should be;

Keep ControlNumber field as a number, try not to make it varchar because it will be not be able to calculate.
First of all remove all existing control number values before trying script.
Then,try this one:
DECLARE #max as bigint
SELECT #max = Max(id)
FROM tblMaster
Select [id],
DupeIdentifier,
-- ControlNumber,
isglobalfamilyunique,
--GlobalFamilyUniqueID,
GlobalFamilyUniqueID,
#max + Row_Number() Over(Order By [id]) [ProposedGlobalFamilyUniqueID],
ControlNumber
From dbo.tblMaster mstr1
where IsGlobalFamilyUnique = 1 and ControlNumber is null
update x
set
GlobalFamilyUniqueID = [ProposedGlobalFamilyUniqueID],
ControlNumber = x.Proposed_Control_Number
from(
Select [id],
DupeIdentifier,
-- ControlNumber,
isglobalfamilyunique,
--GlobalFamilyUniqueID,
GlobalFamilyUniqueID,
Row_Number() Over(Order By [id]) [ProposedGlobalFamilyUniqueID],
ControlNumber,
#max + Row_Number() Over(Order By [id]) as Proposed_Control_Number
From dbo.tblMaster mstr1
Where IsGlobalFamilyUnique = 1 and ControlNumber is null
)x

Related

How to get one column of one record in SQL query?

I try to get full name of #MechanicExpertTable table by select query but get error that
Incorrect syntax near the keyword 'SELECT'.
My code:
DECLARE #MechanicExpertTable AS TABLE
(
Id INT,
FirstName NVARCHAR(128),
LastName NVARCHAR(128)
);
INSERT INTO #MechanicExpertTable
SELECT
PROFILE.Id,
PROFILE.FirstName,
PROFILE.LastName
FROM
EstimatedRialMechanicExpert
INNER JOIN
PROFILE ON EstimatedRialMechanicExpert.ProfileId = PROFILE.Id
WHERE
EstimatedRialId = #id
DECLARE #MechanicExpert1 NVARCHAR(128) =
SELECT TOP(1)
ROW_NUMBER() OVER(ORDER BY Id ASC) AS rownumber,
#MechanicExpertTable.FirstName + ' ' + #MechanicExpertTable.LastName
FROM
#MechanicExpertTable
WHERE
rownumber = 3
How to fix this?
If you want to get the full name for а specific position, try with the following example. In your case, ROW_NUMBER() is used without PARTITION BY, so TOP(1) is not necessary.
Input:
DECLARE #MechanicExpertTable AS TABLE (
Id INT,
FirstName NVARCHAR(128),
LastName NVARCHAR(128)
);
INSERT INTO #MechanicExpertTable
(Id, FirstName, LastName)
VALUES
(1, 'FirstName1', 'LastName1'),
(2, 'FirstName2', 'LastName2'),
(6, 'FirstName6', 'LastName6'),
(7, 'FirstName7', 'LastName7'),
(9, 'FirstName9', 'LastName9')
T-SQL:
DECLARE #MechanicExpert1 NVARCHAR(128)
SELECT TOP(1) #MechanicExpert1 = FullName
FROM (
SELECT
ROW_NUMBER() OVER(ORDER BY Id ASC) AS rownumber,
FirstName + ' ' + LastName AS FullName
FROM #MechanicExpertTable
) t
WHERE rownumber = 3
PRINT #MechanicExpert1
Output:
FirstName6 LastName6
Missing parentheses. Add () for your sub query as and the code should be as below-
DECLARE #MechanicExpert1 NVARCHAR(128) =
(
SELECT TOP 1 T
FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY Id ASC) AS rownumber,
#MechanicExpertTable.FirstName + ' ' + #MechanicExpertTable.LastName AS T
FROM #MechanicExpertTable
)A WHERE rownumber = 3
)
Note: I have added TOP 1 in the selection as it was available in your script. Basically when you are filtering with RowNumber = 3 there are no chance of coming multiple rows. You can remove "TOP 1" from the script.

How to write this procedure to get auto-increment alphanumeric id in SQL Server?

Table structure is as follows:
CREATE TABLE tblContact
(
SrNo DECIMAL IDENTITY(1,1) NOT NULL,
InquiryId VARCHAR(10) PRIMARY KEY,
SenderName VARCHAR(50),
SenderEmail VARCHAR(200),
SenderSubject VARCHAR(50),
SenderMessage VARCHAR(MAX),
IsActive BIT DEFAULT(1),
IsDelete BIT DEFAULT(0),
CreatedOn DATETIME DEFAULT(GETDATE()),
CreatedBy VARCHAR(10),
UpdatedOn DATETIME,
UpdatedBy VARCHAR(10)
)
Procedure listing is as follows:
CREATE PROC Usp_GetNewInquiryId
AS
BEGIN
IF NOT EXISTS(SELECT InquiryId FROM JobPortal.dbo.tblContact)
DECLARE #PrefixValue VARCHAR(10) = 'INQ'
DECLARE #InitialValue DECIMAL(10) = 1001
SELECT InquiryId = #PrefixValue + CAST(ISNULL(MAX(InquiryId), #InitialValue) AS VARCHAR(10))
FROM JobPortal.dbo.tblContact
ELSE
/* here I want to eliminate the word 'INQ' from 'INQ1001' towards left side and do increment 1002 from 1001, lastly want to select INQ1002 and so on... */
SELECT TOP 1
InquiryId = #PrefixValue + CONVERT(VARCHAR(10), SUBSTRING(InquiryId, 4, 4)) + 1
FROM JobPortal.dbo.tblContact
ORDER BY InquiryId DESC
END
Desired Output:
If table is empty then InquiryId=INQ1001
Otherwise InquiryId=INQ1002
If you want to return the "next available" InquiryId for tblContact, I would do this:
CREATE PROCEDURE Usp_GetNewInquiryId
AS
BEGIN
IF NOT EXISTS (SELECT InquiryId FROM tblContact)
SELECT 'INQ1001'
ELSE
SELECT TOP 1 'INQ' + CONVERT(VARCHAR,CONVERT(INT,REPLACE(InquiryId,'INQ','')) + 1) FROM tblContact ORDER BY InquiryId DESC
END

How can I put a Transac SQL block into a function that I can reuse in Stored Procedures?

I have code to take the [Correct] column of a table with a particular QuestionId and make it it to a character string:
Here's the code that was suggested to me. It really just has one input which is the [QuestionUId] and one output which is a string looking like "001110" or "00111" or "111" etc.
-- I need to actually search by QuestionUId so I have this to get the QuestionId
DECLARE #QuestionId int;
SELECT #QuestionId = QuestionID
FROM dbo.question
Where QuestionUId = '87e6bbac-651f-4fdb-862b-412979f71847';
;WITH Partitioned AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY QuestionId ORDER BY AnswerId ASC) AS RowNumber
, COUNT(1) OVER (PARTITION BY QuestionId) AS ColumnCount
, CONVERT(VARCHAR(MAX), Correct) AS Correct
FROM
#Answers
WHERE
[QuestionId] = #QuestionId
),
Concatenated AS (
SELECT RowNumber, ColumnCount, Correct FROM Partitioned WHERE RowNumber = 1
UNION ALL
SELECT
P.RowNumber
, P.ColumnCount
, C.Correct + P.Correct AS Correct
FROM
Partitioned P
INNER JOIN Concatenated C
ON P.RowNumber = C.RowNumber + 1
)
SELECT
CONVERT(VARCHAR(20), Correct) AS Correct
FROM
Concatenated
WHERE
RowNumber = ColumnCount
The code works but I would like to make this code available so it can be used by more than one stored procedure.
Can someone tell me is there a way I can put this code into a function or should I just put it into another stored procedure and if so then how could I do that and how could I call it ?
FYI here's the tables that are used and some sample input and output data:
CREATE TABLE [dbo].[Question] (
[QuestionId] INT,
[QuestionUId] UNIQUEIDENTIFIER
)
CREATE TABLE [dbo].[Answer] (
[AnswerId] INT IDENTITY (1, 1) NOT NULL,
[QuestionId] INT NOT NULL,
[Correct] BIT NULL
);
AnswerId QuestionId Correct >>>>> needed a string "001"
19 8 0
20 8 0
21 8 1
AnswerId QuestionId Correct >>>>> needed a string "10"
22 9 1
23 9 0
As far as I understand your code returns a single varchar value. So you can create scalar function from it. It will look something like that:
CREATE FUNCTION dbo.MyFunc
(
#QuestionId int
)
RETURNS varchar(20)
AS
BEGIN
DECLARE #RetVal varchar(20)
-- I need to actually search by QuestionUId so I have this to get the QuestionId
;WITH Partitioned AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY QuestionId ORDER BY AnswerId ASC) AS RowNumber
, COUNT(1) OVER (PARTITION BY QuestionId) AS ColumnCount
, CONVERT(VARCHAR(MAX), Correct) AS Correct
FROM
#Answers
WHERE
[QuestionId] = #QuestionId
),
Concatenated AS (
SELECT RowNumber, ColumnCount, Correct FROM Partitioned WHERE RowNumber = 1
UNION ALL
SELECT
P.RowNumber
, P.ColumnCount
, C.Correct + P.Correct AS Correct
FROM
Partitioned P
INNER JOIN Concatenated C
ON P.RowNumber = C.RowNumber + 1
)
SELECT
#RetVal = CONVERT(VARCHAR(20), Correct) AS Correct
FROM
Concatenated
WHERE
RowNumber = ColumnCount
RETURN #RetVal
END
Then you call call it from any other T-SQL code (queries, procedures, other functions):
DECLARE #QuestionId int;
SELECT #QuestionId = QuestionID
FROM dbo.question
Where QuestionUId = '87e6bbac-651f-4fdb-862b-412979f71847';
SELECT dbo.MyFunc(#QuestionId)

SQL counting total rows from temporary table in a table valued function

I need the number of total rows inserted in #t, if #total equals 1.
How can I do that?
ALTER FUNCTION [dbo].[myfunction]
(
#ID int = NULL,
#years int = NULL,
,#total BIT = 0
)
RETURNS #t TABLE (
RowNum int,
ID int,
years int,
)
AS
BEGIN
INSERT INTO #t
SELECT
ROW_NUMBER() OVER(ORDER BY years) AS RowNum,
ID,
years,
FROM dbo.mytable
WHERE ..
RETURN
END
The look of the results should be:
Total RowNum ID year
-------------------------------------
3 1 101 2014
3 2 102 2015
3 3 103 2016
Thanks!
RETURNS #t TABLE (
Total int,
RowNum int,
ID int,
years int,
)
...
INSERT INTO #t
SELECT
NULL,
ROW_NUMBER() OVER(ORDER BY years) AS RowNum,
ID,
years,
FROM dbo.mytable
WHERE ..
...
IF(#total=1) BEGIN
DECLARE #Count INT
SELECT #Count=COUNT(*) FROM #t
UPDATE #t SET Total=#Count
END
RETURN

SQL SERVER 2008 final select command with stored procedure

i guess it is trivial to get it done right .
in the screen-shot below each user(userid) has two results (which is a kind of a duplicate)
how can i fix query to get only one result per user
(each user can have 2 sets of "TimeIn" and "TimeOut" activities)
so if given user does have a second "entrance" but did not leave yet
i need only the first closed entrance/leave + second entrance/still working
here is the Stored Procedure
create table #tmp (tId int, UserId int,
TimeIn1 smalldatetime, [TimeOut1] smalldatetime,
TimeIn2 smalldatetime, [TimeOut2] smalldatetime, tId2 int,
ActiveDate smalldatetime, ReasonID int, Name nvarchar(100), ReasonType nvarchar(100),
TotalMins int)
insert into #tmp (tId, UserId, TimeIn1, TimeOut1, ActiveDate, ReasonID, Name, ReasonType)
SELECT
t1.tId, t1.UserId, t1.TimeIn, t1.[TimeOut], t1.ActiveDate, t1.ReasonID, tblCustomers.name,tblTimeReas.ReasonType
FROM tblTime t1
inner join tblTimeReas on t1.ReasonID = tblTimeReas.ReasonID
inner join tblCustomers on t1.UserId=tblCustomers.custID
where (t1.userid in (select custID from tblCustomers where Classification =35) )
and (DATEPART(DAY,t1.timein)= DATEPART(DAY,GETDATE()))
and (DATEPART(MONTH,t1.timein)= DATEPART(MONTH,GETDATE()))
and (DATEPART(YEAR,t1.timein)= DATEPART(YEAR,GETDATE()))
update #tmp
set tId2 = (select top 1 tId from
tblTime t2 where (userid in (select custID from tblCustomers where Classification =35)) and DATEDIFF(day,t2.timein,#tmp.timein1)=0
and t2.tId>#tmp.tId order by tId asc)
update #tmp
set TimeIn2 = (select TimeIn from tblTime where tId=tId2),
TimeOut2 = (select [TimeOut] from tblTime where tId=tId2)
update #tmp set TotalMins = (
isnull(DATEDIFF(minute,timein1,timeout1),0)+
isnull(DATEDIFF(minute,timein2,timeout2),0)
)
select * from #tmp order by TimeIn1
drop table #tmp
dont know how , i didn't take a course for sql server & databse but this is my final code for
much flexable filtering
create table #tmp (tId int, UserId int,
TimeIn1 smalldatetime, [TimeOut1] smalldatetime,
ActiveDate smalldatetime, ReasonID int, Name nvarchar(100), ReasonType nvarchar(100),
TotalMins int)
insert into #tmp (tId, UserId, TimeIn1, TimeOut1, ActiveDate, ReasonID, Name, ReasonType)
SELECT
t1.tId, t1.UserId, t1.TimeIn, t1.[TimeOut], t1.ActiveDate, t1.ReasonID, tblCustomers.name,tblTimeReas.ReasonType
FROM tblTime t1
inner join tblTimeReas on t1.ReasonID = tblTimeReas.ReasonID
inner join tblCustomers on t1.UserId=tblCustomers.custID
where (t1.userid in (select custID from tblCustomers where Classification Like '%,35%') )
and (DATEPART(DAY,t1.timein)= DATEPART(DAY,GETDATE()))
and (DATEPART(MONTH,t1.timein)= DATEPART(MONTH,GETDATE()))
and (DATEPART(YEAR,t1.timein)= DATEPART(YEAR,GETDATE()))
and TimeOut is null
update #tmp set TotalMins = (
isnull(DATEDIFF(minute,timein1,GETDATE()),0)
)
select *from #tmp order by TimeIn1
drop table #tmp

Resources