If it's possible, I would like to know how to combine the two UPDATE statements and whether this would save performance. Query currently executes in 3 seconds but will continue to grow.
Bonus points if you know of neater, more elegant filtering in my CASE and WHERE statements.
Thanks
DECLARE #PartRevision TABLE
(
OriginalPart VARCHAR(50) NULL,
PartNum VARCHAR(50) NULL,
Revision VARCHAR(50) NULL,
[Language] VARCHAR(50) NULL,
Hierarchy VARCHAR(50) NULL
)
INSERT INTO #PartRevision
(
OriginalPart,
PartNum,
Revision,
[Language],
Hierarchy
)
SELECT
part_no
,''
,''
,''
,''
FROM dbo.PartMaster
;
UPDATE #PartRevision
SET PartNum = SUBSTRING(OriginalPart,1,6)
,Revision = SUBSTRING(RIGHT(OriginalPart, LEN(OriginalPart) - 6),1,2)
,[Language] = CASE
WHEN LEN(RIGHT(OriginalPart, LEN(OriginalPart) - 6)) = 2 THEN ''
WHEN RIGHT(OriginalPart, LEN(OriginalPart) - 6) = 'DEV' THEN ''
ELSE RIGHT(RIGHT(OriginalPart, LEN(OriginalPart) - 6), (LEN(RIGHT(OriginalPart, LEN(OriginalPart) - 6)) -2))
END
FROM #PartRevision
--business designed/approved filter--
WHERE LEFT(OriginalPart, 1) NOT IN ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z')
AND OriginalPart NOT IN ('40T', '45T', '46AJ', '2044', '16NA', '12NA', '86TCE', '86TNA', '86TAS', '82TNA', '66TNA', '643TH', '843TH', '99000', '61TNA', '3215NA', '4626NA', '7127NA', '9250NA', '63AJNA', '1056TH', '8841NA', '3219NA', '1044TH', '3226NA', '4632NA', '4740NA', '8831NA', '208922', '7135NA', '85AJNA', '3220NA', '201975B', '201520A', '200989B', '109271B', '1044THS', '200465B', '202207A', '201436A', '2PREPAY', '200545A', '1056THS', '111169B', '30AJENA', '202204B', '202140B', '200551B', '201452B', '310142B', '2p5 ARA', '202100A', '111170B', '218999A', '1256THS', '202061B', '107212F', '202698A', '201974B', '201114B')
;
UPDATE #PartRevision
SET PartNum = CONCAT(PartNum, [Language])
FROM #PartRevision
;
SELECT * FROM #PartRevision
The end result. Solved the problem, but am still curious about optimizing the UPDATES.
BEGIN
DECLARE #PartRevision TABLE
(
OriginalPart VARCHAR(50) NULL,
PartNum VARCHAR(50) NULL,
Revision VARCHAR(50) NULL,
[Language] VARCHAR(50) NULL,
Hierarchy VARCHAR(50) NULL
)
DECLARE #HierLookup TABLE
(
Hierarchy INT IDENTITY(1,1) PRIMARY KEY
,RevisionCode VARCHAR(10) NOT NULL
)
DECLARE #RevisionGen TABLE
(
Alphabet VARCHAR(10) NOT NULL,
BaseRevision VARCHAR(10) NULL
)
DECLARE #iAlphabet INT = 65
DECLARE #iBaseRevision INT = 65
--Start build of Hierarchy Lookup Table (#HierLookup)
--INSERT A-Z into #RevisionGen
WHILE #iAlphabet < 91
BEGIN
INSERT INTO #RevisionGen
(
Alphabet
)
VALUES
(
CHAR(#iAlphabet)
)
SET #iAlphabet = #iAlphabet + 1;
END
;
--Final INSERTS and UPDATES to #HierLookup
WHILE #iBaseRevision < 91
BEGIN
UPDATE #RevisionGen
SET BaseRevision = CHAR(#iBaseRevision);
;
INSERT INTO #HierLookup
(
RevisionCode
--,Hierarchy
)
SELECT CONCAT(BaseRevision, Alphabet)
FROM #RevisionGen;
SET #iBaseRevision = #iBaseRevision + 1
;
END
;
--Starting INSERTS and UPDATES to #PartRevision
--Get base Part data from ETL Data Warehouse
INSERT INTO #PartRevision
(
OriginalPart,
PartNum,
Revision,
[Language],
Hierarchy
)
SELECT
PART_NO
,''
,''
,''
,''
FROM man.Stage_Gue_InventoryPart
;
--Start parsing Parts data
UPDATE #PartRevision
SET PartNum = SUBSTRING(OriginalPart,1,6)
,Revision = SUBSTRING(RIGHT(OriginalPart, LEN(OriginalPart) - 6),1,2)
,[Language] = CASE
WHEN LEN(OriginalPart) - 6 = 2 THEN ''
WHEN RIGHT(OriginalPart, LEN(OriginalPart) - 6) = 'DEV' THEN ''
ELSE RIGHT(RIGHT(OriginalPart, LEN(OriginalPart) - 6), (LEN(OriginalPart) - 6) -2)
END
FROM #PartRevision
--business approved filter--
WHERE LEFT(OriginalPart, 1) NOT LIKE '[a-z]%'
AND OriginalPart NOT IN ('40T', '45T', '46AJ', '2044', '16NA', '12NA', '86TCE', '86TNA', '86TAS', '82TNA', '66TNA', '643TH', '843TH', '99000', '61TNA', '3215NA', '4626NA', '7127NA', '9250NA', '63AJNA', '1056TH', '8841NA', '3219NA', '1044TH', '3226NA', '4632NA', '4740NA', '8831NA', '208922', '7135NA', '85AJNA', '3220NA', '201975B', '201520A', '200989B', '109271B', '1044THS', '200465B', '202207A', '201436A', '2PREPAY', '200545A', '1056THS', '111169B', '30AJENA', '202204B', '202140B', '200551B', '201452B', '310142B', '2p5 ARA', '202100A', '111170B', '218999A', '1256THS', '202061B', '107212F', '202698A', '201974B', '201114B', '216610')
;
--Final update to Part Number
UPDATE #PartRevision
SET PartNum = CONCAT(PartNum, [Language])
FROM #PartRevision
;
--INSERT Hierarchy numbers from #HierLookup table
UPDATE #PartRevision
SET Hierarchy = CASE
WHEN l.Hierarchy = '' THEN 1
ELSE l.Hierarchy
END
FROM #PartRevision AS p
LEFT JOIN #HierLookup AS l
ON l.RevisionCode = p.Revision
;
--UPDATE ETL, Pre-Merge Table
UPDATE man.Stage_Gue_InventoryPart
SET PART_NO = CASE
WHEN PartNum = '' THEN OriginalPart
ELSE PartNum
END,
ENG_REVISION = Revision
--REV_SEQ = Hierarchy
FROM #PartRevision
WHERE PART_NO = OriginalPart
;
END
Related
I got a problem regarding missing rows in a table that is giving me a headache.
As base data, I have the following table:
declare #table table
(
id1 int,
id2 int,
ch char(1) not null,
val int
)
insert into #table values (1112, 121, 'A', 12)
insert into #table values (1351, 121, 'A', 13)
insert into #table values (1411, 121, 'B', 81)
insert into #table values (1312, 7, 'C', 107)
insert into #table values (1401, 2, 'A', 107)
insert into #table values (1454, 2, 'D', 107)
insert into #table values (1257, 6, 'A', 1)
insert into #table values (1269, 6, 'B', 12)
insert into #table values (1335, 6, 'C', 12)
insert into #table values (1341, 6, 'D', 5)
insert into #table values (1380, 6, 'A', 3)
The output should be ordered by id2 and follow a fixed sequence of ch, which should repeat until next id2 begins.
Sequence:
'A'
'B'
'C'
'D'
If the sequence or the pattern is interrupted, it should fill the missing rows with null, so that i get this result table:
id1 id2 ch val
----------------------------
1112 121 'A' 12
NULL 121 'B' NULL
NULL 121 'C' NULL
NULL 121 'D' NULL
1351 121 'A' 13
1411 121 'B' 81
NULL 121 'C' NULL
NULL 121 'D' NULL
NULL 7 'A' NULL
NULL 7 'B' NULL
1312 7 'C' 107
NULL 7 'D' NULL
1401 2 'A' 107
NULL 2 'B' NULL
NULL 2 'C' NULL
1454 2 'D' 107
and so on...
What I'm looking for is a way to do this without iterations.
I hope someone can help!
Thanks in advance!
A solution might be this:
declare #table table ( id1 int, id2 int, ch char(1) not null, val int )
insert into #table values (1112, 121, 'A', 12)
,(1351, 121, 'A', 13),(1411, 121, 'B', 81),(1312, 7, 'C', 107),(1401, 2, 'A', 107)
,(1454, 2, 'D', 107),(1257, 6, 'A', 1),(1269, 6, 'B', 12),(1335, 6, 'C', 12)
,(1341, 6, 'D', 5),(1380, 6, 'A', 3)
;with foo as
(select
*
,row_number() over (partition by id2 order by id1) rwn
,ascii(isnull(lag(ch,1) over (partition by id2 order by id1),'A'))-ascii('A') prev
,count(*) over (partition by id2,ch) nr
,ascii(ch)-ascii('A') cur
from #table
)
,bar as
(
select
*,case when cur<=prev and rwn>1 then 4 else 0 end + cur-prev step
from foo
)
,foobar as
(
select *,sum(step) over (partition by id2 order by id1 rows unbounded preceding) rownum
from bar
)
,iterations as
(
select id2,max(nr) nr from foo
group by id2
)
,blanks as
(
select
id2,ch chnr,char(ch+ascii('A') )ch,ROW_NUMBER() over (partition by id2 order by c.nr,ch)-1 rownum,c.nr
from iterations a
inner join (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) c(nr)
on c.nr<=a.nr
cross join (values (0),(1),(2),(3)) b(ch)
)
select
b.id1,a.id2,a.ch,b.val
from blanks a
left join foobar b
on a.id2=b.id2 and a.rownum=b.rownum
order by a.id2,a.rownum
I first make the query "foo" which looks at the row number and gets the previous value for ch for each id2.
"bar" then finds how many missing values there are between the rows. For instance If the previous was an A and the current is a c then there are 2. If the previous was an A and the current is an A, then there are 4!
"foobar" then adds the steps, thus numbering the original rows, where they should be in the final output.
"iterations" counts the number of times the "ABCD" rows should appear.
"BLANKS" then is all the final rows, that is for each id2, it outputs all the "ABCD" rows that should be in the final output, and numbers them in rownum
Finally I left join "foobar" with "BLANKS" on id2 and rownum. Thus we get the correct number of rows, and the places where there are values in the original is output.
If you can manage to add an extra column in your table, that defines which [id2] are part from the same sequence you can try this:
declare #table table
(
id1 int,
id2 int,
ch char(1) not null,
val int,
category int -- extra column
)
insert into #table values (1112, 121, 'A', 12, 1)
insert into #table values (1351, 121, 'A', 13, 2)
insert into #table values (1411, 121, 'B', 81, 2)
insert into #table values (1312, 7, 'C', 107, 3)
insert into #table values (1401, 2, 'A', 107, 4)
insert into #table values (1454, 2, 'D', 107, 4)
insert into #table values (1257, 6, 'A', 1, 5)
insert into #table values (1269, 6, 'B', 12, 5)
insert into #table values (1335, 6, 'C', 12, 5)
insert into #table values (1341, 6, 'D', 5, 5)
insert into #table values (1380, 6, 'A', 3, 5)
DECLARE #sequence table (seq varchar(1))
INSERT INTO #sequence values ('A'), ('B'), ('C'), ('D')
SELECT b.id1, a.id2, a.seq, b.val, a.category
INTO #T1
FROM (
SELECT *
FROM #table
CROSS JOIN #sequence
) A
LEFT JOIN (
SELECT * FROM #table
) B
ON 1=1
AND a.id1 = b.id1
AND a.id2 = b.id2
AND a.seq = b.ch
AND a.val = b.val
;WITH rem_duplicates AS (
SELECT *, dup = ROW_NUMBER() OVER (PARTITION by id2, seq, category ORDER BY id1 DESC)
FROM #T1
) DELETE FROM rem_duplicates WHERE dup > 1
SELECT * FROM #T1 ORDER BY id2 DESC, category ASC, seq ASC
DROP TABLE #T1
I'm little confused by your output, try this:
Update
DECLARE #table TABLE
(
row INT IDENTITY(1, 1) ,
id1 INT ,
id2 INT ,
ch CHAR(1) NOT NULL ,
val INT
);
DECLARE #Sequence TABLE ( ch3 CHAR(1) NOT NULL );
INSERT INTO #Sequence
VALUES ( 'A' );
INSERT INTO #Sequence
VALUES ( 'B' );
INSERT INTO #Sequence
VALUES ( 'C' );
INSERT INTO #Sequence
VALUES ( 'D' );
INSERT INTO #table
VALUES ( 1112, 121, 'A', 12 );
INSERT INTO #table
VALUES ( 1351, 121, 'A', 13 );
INSERT INTO #table
VALUES ( 1411, 121, 'B', 81 );
INSERT INTO #table
VALUES ( 1312, 7, 'C', 107 );
INSERT INTO #table
VALUES ( 1401, 2, 'A', 107 );
INSERT INTO #table
VALUES ( 1454, 2, 'D', 107 );
INSERT INTO #table
VALUES ( 1257, 6, 'A', 1 );
INSERT INTO #table
VALUES ( 1269, 6, 'B', 12 );
INSERT INTO #table
VALUES ( 1335, 6, 'C', 12 );
INSERT INTO #table
VALUES ( 1341, 6, 'D', 5 );
INSERT INTO #table
VALUES ( 1380, 6, 'A', 3 );
SELECT r.id1 ,
fin.id2 ,
ch3 ,
r.val
FROM ( SELECT *
FROM ( SELECT CASE WHEN r.chd - l.chd = 1 THEN 0
ELSE 1
END [gap in sq] ,
l.*
FROM ( SELECT id2 ,
ASCII(ch) chd ,
ch ,
val ,
id1 ,
row
FROM #table
) AS l
LEFT JOIN ( SELECT id2 ,
ASCII(ch) chd ,
row
FROM #table
) AS r ON l.row = r.row - 1
) AS temp ,
#Sequence s
WHERE temp.[gap in sq] = 1
OR ( temp.[gap in sq] = 0
AND s.ch3 = temp.ch
)
) AS fin
LEFT JOIN #table r ON r.id2 = fin.id2
AND r.id1 = fin.id1
AND r.ch = fin.ch3
Newbie question... looking for the fastest way to update a new column based on the existence of a value from another table, while replacing values.
Example, below, taking the words 'Bought a car' with 'car' into another table. The problem is 'Bought a car' is into another table.
I did a hack to reselect the value and do a replace, but with more rows, the performance is horrible, taking up to 3 to 5 minutes to perform.
Oh SQL Gurus, what is the best way to do this?
Example
DECLARE #Staging_Table TABLE
(
ACCTID INT IDENTITY(1,1),
NAME VARCHAR(50),
PURCHASES VARCHAR(255)
)
INSERT INTO #Staging_Table (Name, Purchases)
VALUES ('John','Bought a table')
INSERT INTO #Staging_Table (Name, Purchases)
VALUES ('Jack','Sold a car')
INSERT INTO #Staging_Table (Name, Purchases)
VALUES ('Mary','Returned a chair')
DECLARE #HISTORY TABLE
(
ACCTID INT IDENTITY(1,1),
NAME VARCHAR(50),
Item VARCHAR(255)
)
INSERT INTO #HISTORY (Name, Item)
VALUES ('John','')
INSERT INTO #HISTORY (Name, Item)
VALUES ('Jack','')
INSERT INTO #HISTORY (Name, Item)
VALUES ('Mary','')
UPDATE #HISTORY
Set ITEM = CASE WHEN EXISTS(
Select ts.Purchases as Output from #Staging_Table ts
where ts.NAME = Name AND ts.PURCHASES LIKE '%table%')
THEN REPLACE((Select ts2.PURCHASES Output
from #Staging_Table ts2 where ts2.NAME = Name AND ts2.PURCHASES LIKE '%table%'),'Bought a ','')
WHEN EXISTS(
Select ts.Purchases as Output from #Staging_Table ts
where ts.NAME = Name AND ts.PURCHASES LIKE '%car%')
THEN REPLACE((Select ts2.PURCHASES Output
from #Staging_Table ts2 where ts2.NAME = Name AND ts2.PURCHASES LIKE '%car%'),'Bought a ','')
End
SELECT * FROM #HISTORY
DECLARE #Staging_Table TABLE
(
ACCTID INT IDENTITY(1, 1) ,
NAME VARCHAR(50) ,
PURCHASES VARCHAR(255)
)
INSERT INTO #Staging_Table
( Name, Purchases )
VALUES ( 'John', 'Bought a table' ),
( 'Jack', 'Sold a car' ),
( 'Mary', 'Returned a chair' )
DECLARE #HISTORY TABLE
(
ACCTID INT IDENTITY(1, 1) ,
NAME VARCHAR(50) ,
Item VARCHAR(255)
)
INSERT INTO #HISTORY
( Name, Item )
VALUES ( 'John', '' ),
( 'Jack', '' ),
( 'Mary', '' )
UPDATE L
SET L.ITEM = ( CASE WHEN R.PURCHASES LIKE '%table%'
THEN REPLACE(R.PURCHASES, 'Bought a ', '')
WHEN R.PURCHASES LIKE '%car%'
THEN REPLACE(R.PURCHASES, 'Sold a ', '')
END )
FROM #HISTORY AS L
JOIN #Staging_Table AS R ON L.NAME = R.NAME
WHERE ( R.PURCHASES LIKE '%table%'
OR R.PURCHASES LIKE '%car%'
)
SELECT *
FROM #HISTORY
I want to retrieve data from the table based on a couple of columns, some with data, other with NULL. In the first code example below, the procedure is fine - all the rows are returned. In the second example no rows are returned - because NULL=NULL return FALSE.
The third example is more or less what I have in mind, when the column has NULL values, then this clause has to be "ignored" and only the data in the first two columns are used to return the rows based on these two columns.
SELECT * FROM XYZ
WHERE col1 IN ('a', 'b')
AND col2 IN ('c', 'd')
AND col3 IN ('e', 'f')
SELECT * FROM XYZ
WHERE col1 IN ('a', 'b')
AND col2 IN ('c', 'd')
AND col3 IN (NULL) --???
SELECT * FROM XYZ
WHERE col1 IN ('a', 'b')
AND col2 IN ('c', 'd')
--AND col3 IN (NULL) --IGNORED
Currently I use a dynamic SQL statement, but is very slow.
SET #EventCodeList =
(SELECT REPLACE(tEventCode, ' ', '') FROM tblActivityPerCC_Config WHERE tCostCenter = #CostCenter)
SET #EventCodeStr =
CASE WHEN #EventCodeList IS NULL THEN ' logs.tEventCode LIKE (''%'') '
ELSE ' logs.tEventCode IN (SELECT qValue FROM nsEMV.dbo.fncReturnCommaDelimitedStringAsTable(#EventCodeList))'
END
SET #SQLString = N'
SELECT
ccg.Field1,
logs.Field2
FROM dbo.tblEMV_Logsheet AS logs
INNER JOIN dbo.tblLookup_EMVEquipment AS ccg ON logs.tEquipmentKey = ccg.tEquipmentKey
WHERE tDate BETWEEN ''' + CONVERT(varchar(30), #BMonth) + ''' AND ''' + CONVERT(varchar(30), #EMonth) + '''
AND logs.tAreaCode IN ('XYZ', 'ABC')
AND ' + #EventCodeStr + ' --THE FOLLOWING COLUMNS MAY HAVE NULL VALUES
AND ' + #SourceStr + '
AND ' + #DestinationStr'
Any help would be appreciated.
IN RESPONSE TO Jayvee's SUGGESTION BELOW:
This does not do what was intended or I do something wrong!
CREATE TABLE #temp
(
value varchar(10),
value2 varchar(10)
)
INSERT INTO #temp (value, value2) SELECT '5', '3'
INSERT INTO #temp (value, value2) SELECT NULL, '2'
INSERT INTO #temp (value, value2) SELECT '4', NULL
INSERT INTO #temp (value, value2) SELECT '6', '2'
INSERT INTO #temp (value, value2) SELECT '6', NULL
INSERT INTO #temp (value, value2) SELECT '6', '4'
INSERT INTO #temp (value, value2) SELECT NULL, '1'
INSERT INTO #temp (value, value2) SELECT NULL, '4'
SELECT value as [value],value2 as [value2] FROM #temp
WHERE ISNULL(value,'') IN ('4')
AND ISNULL(value2,'') IN ('4')
DROP TABLE #temp
Try IS NULL
SELECT * FROM XYZ
WHERE col1 IN ('a', 'b')
AND col2 IN ('c', 'd')
AND col3 IS NULL -- Instead of IN (NULL)
for each column test it against your parameter and include the IS NULL test, combine these with parentheses, like this:
SELECT
*
FROM XYZ
WHERE (col1 IN ('a', 'b') OR col1 IS NULL)
AND (col2 IN ('c', 'd') OR col2 IS NULL)
AND (col3 IN (NULL) OR col3 IS NULL)
here col3 IN (NULL) is used to demonstrate a parameter that was not provided
something like this should work:
SELECT * FROM XYZ
WHERE ISNULL(col1,'') IN ('a', 'b','')
AND ISNULL(col2,'') IN ('c', 'd','')
AND ISNULL(col3,'') IN ('')
I want to reduce the time it takes for one of my stored procs that currently uses the following logic to calculate the date field, both in Select and Group portion:
left(datename(month, a.QXP_REPORT_DATE), 3) + ' ''' + right(datename(year, a.QXP_REPORT_DATE), 2)
Would a simple lookup table take less time? If so, then how would I populate for the following fields for all dates in the last 2 years?
CREATE TABLE #CALENDAR(
FULLDATE DATETIME,
MONTHNAME NVARCHAR(3),
sYEAR SMALLINT
)
INSERT INTO #CALENDAR
SELECT '4/19/2011', left(datename(month, '4/19/2011'), 3), right(datename(year, '4/19/2011'), 2)
I'm starting to think maybe a function call would be better than a lookup table. Here is all of my SQL stored proc:
DECLARE
#FirstMonthDate DATETIME,
#LastMonthDate DATETIME,
#TheLevel INT,
#ProductGroup VARCHAR(255),
#TheCategory VARCHAR(255),
#ListNumber VARCHAR(50)
--AS
-- SET NOCOUNT ON;
--ComplaintTrendingDrillDown3p '3/1/10', '3/31/11 23:59:59', 3 , 'RealTime IVD', 'Procedure Not Followed', ''
SET #FirstMonthDate = '3/1/11'
SET #LastMonthDate = '3/31/11 23:59:59'
SET #TheLevel = 3
SET #ProductGroup = 'RealTime IVD'
SET #TheCategory = 'Procedure Not followed'
--SET #ListNumber = '2G31-90'
DECLARE #SelectedLevels table (LevelId int not null primary key)
declare #OneYearAgo datetime
set #OneYearAgo = dateadd(year, -1, #FirstMonthDate)
IF #TheLevel = 3
BEGIN
INSERT INTO #SelectedLevels (LevelId) VALUES (1)
INSERT INTO #SelectedLevels (LevelId) VALUES (2)
END
ELSE if #TheLevel = 5
BEGIN
INSERT INTO #SelectedLevels (LevelId) VALUES (0)
INSERT INTO #SelectedLevels (LevelId) VALUES (1)
INSERT INTO #SelectedLevels (LevelId) VALUES (2)
END
ELSE
BEGIN
INSERT INTO #SelectedLevels (LevelId) VALUES (#TheLevel)
END
SELECT count(distinct a.QXP_EXCEPTION_NO) AS QXP_EXCEPTION_NO, PRODUCT_CODE_STD, a.qxp_short_desc,
left(datename(month, a.QXP_REPORT_DATE), 3) + ' ''' +
right(datename(year, a.QXP_REPORT_DATE), 2) AS MonthYear ,
CASE WHEN a.QXP_SHORT_DESC = #TheCategory OR ISNULL(#TheCategory, '') = '' THEN 1 ELSE 0 END AS SELECTED_CATEGORY
FROM ALL_COMPLAINTS a
INNER JOIN #SelectedLevels F ON A.[LEVEL] = F.LevelId
LEFT OUTER JOIN MANUAL.PRODUCTS b ON a.EPA_PRD_CODE = b.LIST_NUMBER
LEFT OUTER JOIN SMARTSOLVE.V_CXP_CUSTOMER_PXP c ON a.QXP_ID = c.QXP_ID
WHERE a.QXP_REPORT_DATE >= #OneYearAgo AND
a.QXP_REPORT_DATE <= #LastMonthDate AND a.QXP_SHORT_DESC <> 'Design Control'
AND (c.QXP_EXCEPTION_TYPE <> 'Non-Diagnostic' OR c.QXP_EXCEPTION_TYPE IS NULL)
AND PRODUCT_GROUP= #ProductGroup
AND (PRODUCT_CODE_STD = #ListNumber OR ISNULL(#ListNumber, '') = '')
and left(datename(month, a.QXP_REPORT_DATE), 3) = 'may'
GROUP BY PRODUCT_CODE_STD, left(datename(month, a.QXP_REPORT_DATE), 3) + ' ''' + right(datename(year, a.QXP_REPORT_DATE), 2) , a.qxp_short_desc
order by left(datename(month, a.QXP_REPORT_DATE), 3) + ' ''' +
right(datename(year, a.QXP_REPORT_DATE), 2), product_code_std, qxp_short_desc
Execution plan recommendations:
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [SMARTSOLVE].[V_CXP_CUSTOMER_PXP] ([QXP_REPORT_DATE],[QXP_UDF_STRING_8],[QXP_XRS_DESCRIPTION])
INCLUDE ([QXP_ID],[QXP_EXCEPTION_NO],[QXP_BASE_EXCEPTION],[QXP_OCCURENCE_DATE],[QXP_COORD_ID],[QXP_ROOT_CAUSE],[QXP_DESCRIPTION],[QXP_QEI_ID],[QXP_EXCEPTION_TYPE],[QXP_UDF_STRING_2],[QXP_UDF_STRING_5],[CXP_ID],[CXP_AWARE_DATE],[QXP_XSV_CODE],[QXP_COORD_NAME],[QXP_ORU_NAME],[QXP_RESOLUTION_DESC],[QXP_CLOSED_DATE],[CXP_CLIENT_CODE],[CXP_CLIENT_NAME])
I have a table contacts.
CREATE TABLE [dbo].[Contacts](
[ContactId] [int] IDENTITY(1,1) NOT NULL,
[ContactCode] [nvarchar](10) NOT NULL, --UNIQUE
[FirstName] [nvarchar](24) NOT NULL,
[MiddleName] [nvarchar](12) NULL,
[LastName] [nvarchar](24) NOT NULL,
CONSTRAINT [PK_Contacts] PRIMARY KEY CLUSTERED
(
[ContactId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
I would like to be able to generate a 10-digit contact code from the stored procedure which should comprise of
First Two Digits of FirstName
First Digit of MiddleName(When MiddleName is not blank)
First Two or Three(When MiddleName is Blank) Digits of Last Name
Four digit number starting from zero.
Example.
John M. Denver = JOMDE-0001
John Denver = JODEN-0001
John Denver = JODEN-0002
Bob Dylan = BODYL-0001
Proposed solution could be a function which could be called from inside the stored procedure before saving the values to the table.
CREATE FUNCTION GetContactCode
(
#FirstName nvarchar(24),
#MiddleName nvarchar(12),
#LastName nvarchar(24)
)
RETURNS nvarchar(10)
AS
BEGIN
RETURN('CODE')
END
Can anybody help?
Using a RANKING clause is one option.
;WITH q AS (
SELECT ContactID
, ContactCode =
UPPER(
SUBSTRING(
SUBSTRING(FirstName, 1, 2)
+ ISNULL(SUBSTRING(MiddleName, 1, 1), '')
+ SUBSTRING(LastName, 1, 3)
, 1, 5)
+ '-')
FROM Contacts
)
SELECT c.*
, q.ContactCode
+ RIGHT(REPLICATE('0', 4)
+ CAST(
RANK() OVER (PARTITION BY q.ContactCode ORDER BY q.ContactID
) AS VARCHAR(4))
, 4)
FROM q INNER JOIN Contacts c ON c.ContactId = q.ContactID
This function should do the trick
CREATE FUNCTION GetContactCode
(
#FirstName nvarchar(24),
#MiddleName nvarchar(12),
#LastName nvarchar(24)
)
RETURNS nchar(10)
AS
BEGIN
declare #contactcode nchar(10)
select top 1 #contactcode = contactCode
from contacts
where
contactcode like left(#FirstName,2)+
case
when #MiddleName is null or #MiddleName = '' then left(#LastName,3)
else left(#MiddleName,1)+left(#LastName,2)
end+'%'
order by contactCode desc
select #Contactcode =
Upper(left(#FirstName,2)+
case
when #MiddleName is null or #MiddleName = '' then left(#LastName,3)
else left(#MiddleName,1)+left(#LastName,2)
end) + '-' +
case
when #ContactCode is null then'0001'
else replace(str(cast(right(#ContactCode,4) as int)+1,4),' ','0')
end
Return #ContactCode
END