I have some specific values I want to extract out of a string in SQL Server, but I'm not sure exactly how to get it done with PATINDEX.
Take this string:
declare #Command nvarchar(500) = 'IF dbo.SomeFunctionFn() = 1 BEGIN EXEC SomeStoredProcPR #RowsPerRun=500000, #RowsPerBatch=10000, #NbrDaysToKeepRpt=7 END'
I want to extract out the values of 500000 (for #RowsPerRun), 10000 for #RowsPerBatch and the value of 7 for #NbrDaysToKeepRpt. The values will be of variable length, so I can't guarantee the #RowsPerRun value will be 6 characters.
Is that possible?
DECLARE #Command NVARCHAR(500) =
'IF dbo.SomeFunctionFn() = 1 BEGIN EXEC SomeStoredProcPR #RowsPerRun=500000, #RowsPerBatch=10000, #NbrDaysToKeepRpt=7 END'
SELECT
SearchItem = srch.Txt,
ItemIndex = st.Pos,
ItemLen = t.Ln,
Item = SUBSTRING(pfx.Txt,1,t.Ln)
FROM (VALUES('#RowsPerRun='),('#RowsPerBatch='),('#NbrDaysToKeepRpt=')) AS srch(Txt)
CROSS APPLY (VALUES(CHARINDEX(srch.Txt,#Command),LEN(srch.Txt))) AS st(Pos,Ln)
CROSS APPLY (VALUES(SUBSTRING(#Command, st.Pos+st.Ln, 500))) AS pfx(Txt)
CROSS APPLY (VALUES(PATINDEX('%[^0-9]%',pfx.Txt)-1)) AS t(Ln);
Returns:
SearchItem ItemIndex ItemLen Item
------------------ ----------- ----------- --------
#RowsPerRun= 59 6 500000
#RowsPerBatch= 79 5 10000
#NbrDaysToKeepRpt= 100 1 7
Note that I included a few extra columns to help you understand what's happening.
Update: Against a table
This is how you would apply this logic to a series of values:
DECLARE #sometable TABLE (CommandId INT IDENTITY, Command NVARCHAR(500));
INSERT #sometable (Command)
VALUES
('IF dbo.SomeFunctionFn() = 1 BEGIN EXEC SomeStoredProcPR #RowsPerRun=500000, #RowsPerBatch=10000, #NbrDaysToKeepRpt=7 END'),
('IF dbo.SomeFunctionFn() = 5 BEGIN EXEC SomeStoredProcPR #RowsPerRun=123, #RowsPerBatch=500, #NbrDaysToKeepRpt=20 END'),
('IF dbo.SomeFunctionFn() = 5 BEGIN EXEC XXX #RowsPerRun=43, #RowsPerBatch=1000, #NbrDaysToKeepRpt=120 END'),
('IF dbo.SomeFunctionFn() = 5 BEGIN EXEC abc.yyy #RowsPerRun=43, #RowsPerBatch=1000, #NbrDaysToKeepRpt=120 END');
SELECT t.CommandId, f.SearchItem, f.Item
FROM #sometable AS t
CROSS APPLY
(
SELECT
SearchItem = srch.Txt,
ItemIndex = st.Pos,
ItemLen = t.Ln,
Item = SUBSTRING(pfx.Txt,1,t.Ln)
FROM (VALUES('#RowsPerRun='),('#RowsPerBatch='),('#NbrDaysToKeepRpt=')) AS srch(Txt)
CROSS APPLY (VALUES(CHARINDEX(srch.Txt,t.Command),LEN(srch.Txt))) AS st(Pos,Ln)
CROSS APPLY (VALUES(SUBSTRING(t.Command, st.Pos+st.Ln, 500))) AS pfx(Txt)
CROSS APPLY (VALUES(PATINDEX('%[^0-9]%',pfx.Txt)-1)) AS t(Ln)
) AS f;
Returns:
CommandId SearchItem Item
----------- ------------------ --------
1 #RowsPerRun= 500000
1 #RowsPerBatch= 10000
1 #NbrDaysToKeepRpt= 7
2 #RowsPerRun= 123
2 #RowsPerBatch= 500
2 #NbrDaysToKeepRpt= 20
3 #RowsPerRun= 43
3 #RowsPerBatch= 1000
3 #NbrDaysToKeepRpt= 120
4 #RowsPerRun= 43
4 #RowsPerBatch= 1000
4 #NbrDaysToKeepRpt= 120
Related
how can i restart this cursor after if condition and want row_number start from one again in answer.want to restart cursor from end point of if condition.
declare #SUM DECIMAL(20,2)
declare #EMPCODE varchar(10)
declare #NETPAY DECIMAL(10,2)
declare ABC scroll cursor for
select EMPCODE,NETPAY from TXXL where DATE='04-30-2015'
open ABC
declare #TEMP table(
EMPCODE varchar(10) primary key,
NETPAY DECIMAL(10,2),
SUM varchar(max)
)
set #SUM=0
fetch first from ABC into #EMPCODE,#NETPAY
while ##fetch_status=0
begin
fetch next from ABC into #EMPCODE,#NETPAY
SET #SUM=#SUM+#NETPAY
if(#SUM<=900000)
insert into #TEMP(EMPCODE,NETPAY,SUM) values(#EMPCODE,#NETPAY,#SUM)
end
select ROW_NUMBER() OVER(ORDER BY EMPCODE) ROWNUMBER,EMPCODE,NETPAY,SUM from #TEMP
close ABC
deallocate ABC
this cursor gives that answer,cursor stop working after 000179 EMPCODE because the sum of next empcode is greater than 900000 i want to start next empcode with ROWnumber 1 and sum like that the sum of this sample :-
ROWNUMBER EMPCODE NETPAY SUM
1 000066 29079.00 29079.00
2 000076 34515.00 63594.00
3 000084 15493.00 79087.00
4 000090 30399.00 109486.00
5 000109 25812.00 135298.00
6 000111 31453.00 166751.00
7 000113 30408.00 197159.00
8 000116 28040.00 225199.00
9 000124 27901.00 253100.00
10 000128 24445.00 277545.00
11 000131 35760.00 313305.00
12 000141 23345.00 336650.00
13 000150 48965.00 385615.00
14 000179 39350.00 424965.00
want answer like that:-
ROWNUMBER EMPCODE NETPAY SUM
1 000066 29079.00 29079.00
2 000076 34515.00 63594.00
3 000084 15493.00 79087.00
4 000090 30399.00 109486.00
5 000109 25812.00 135298.00
6 000111 31453.00 166751.00
7 000113 30408.00 197159.00
8 000116 28040.00 225199.00
9 000124 27901.00 253100.00
10 000128 24445.00 277545.00
11 000131 35760.00 313305.00
12 000141 23345.00 336650.00
13 000150 48965.00 385615.00
14 000179 39350.00 424965.00
1 000181 40814.00 40814.00
2 000182 24335.00 65149.00
3 000196 29439.00 94588.00
4 ----- ------ -------
5 -------- ----- -------
I am trying to build a view that looks at a table that has three columns; Building, Lane, Lot. I need to be able to loop through the table dynamically to display the Building, Lane and Lot all on one row.
Sample:
>Building Lane Lot
> 1 1001 56789
> 1 1002 12489
> 1 1002 37159
> 1 1002 71648
> 3 3001 27489
> 3 3001 67154
> 3 3002 47135
> 3 3003 84271
> 3 3003 96472
> 3 3003 94276
Results
> Building Lane Lots
> 1 1001 56789
> 1 1002 12489, 37159, 71648
> 3 3001 27489, 67154
> 3 3002 47135
> 3 3003 84271, 96472, 94276
I tried a recursion union but received a message that I had exceded the max amount of 100.
I also tried a loop but it just kept going and did not concantenate as I had hoped.
So far in the table there are over 300 lot numbers for one building in one lane with the potential of huders more.
It looks like you're looking for something similar to the below script (see this SQL Fiddle example):
DECLARE #row TABLE (
A VARCHAR(1),
AA VARCHAR(1),
B VARCHAR(4)
)
INSERT INTO #row VALUES(1,1,1001)
INSERT INTO #row VALUES(1,1,1002)
INSERT INTO #row VALUES(1,1,1003)
INSERT INTO #row VALUES(1,2,1001)
INSERT INTO #row VALUES(2,1,1001)
INSERT INTO #row VALUES(2,1,1002)
INSERT INTO #row VALUES(2,1,1003)
INSERT INTO #row VALUES(2,1,1004)
INSERT INTO #row VALUES(2,1,1005)
INSERT INTO #row VALUES(2,2,1001)
INSERT INTO #row VALUES(2,2,1002)
INSERT INTO #row VALUES(3,1,1001)
SELECT *
FROM #row
SELECT r1.A
, r1.AA
, STUFF((SELECT ', ' + r2.B AS [text()]
FROM #row r2
WHERE r1.A = r2.A AND r1.AA = r2.AA
ORDER BY r2.B
FOR XML PATH('')),1,1,'') AS "Row"
FROM #row r1
GROUP BY A, AA
So for your query, it will look something like this:
SELECT r1.Building
, r1.Lane
, STUFF((SELECT ', ' + r2.Lot AS [text()]
FROM YourTable r2
WHERE r1.Building = r2.Building AND r1.Lane = r2.Lane
ORDER BY r2.Lot
FOR XML PATH('')),1,1,'') AS "Row"
FROM YourTable r1
GROUP BY Building, Lane
I have 4 tables Position, Employee, Training and Trmatrix.
Table Position
PositionId PosName TrainingId
1 developer 1,2,3
2 Designer 4,5
3 BDA 2,3,6
Table Employee
Employeeid Ename Posid Courseid
1 Alex 1 4
2 Shaun 2 1,2,3
3 Hales 3
Table Training
Trainingid Trainingname
1 JAVA
2 Dot Net
3 PHP
4 Photoshop
5 JQUERY
6 Client Handling
TrMatrix
TrmatId TrID empID
1 1 1
2 2 1
3 3 1
4 4 1
5 4 2
6 5 2
7 1 2
8 2 2
9 2 3
10 3 3
foreign Key relation
trmatrix trId corresponds to the trainingID of the trainingtable.
Employee posid corresponds to the PositionId of the Positiontable.
Employee courseId corresponds to the trainingId of the trianingtable.
BY basic Aim is to get that course/trainingname which is no present in the
EMployee.Courseid column in correspondance to the trmatrix table,
which defines that I have to get the all entries from the trmatrix table for which there is no entry in the employee table Courseid column.
Suppose in case of Alex I have to fetch all the data from the trmatrix table except for course 4 since it is present in the courseid column of the Employee table, so it would return course no 1,2,3 not the no 4.
I am Newbie to the SQL so please help me out with this problem.
Thanks in advance
To start with, you should make PositionTraining and EmployeeCourse tables as well:
PositionTraining
PositionId TrainingId
1 1
1 2
1 3
2 4
2 5
3 2
3 3
3 6
EmployeeCourse
Employeeid Courseid
1 4
2 1
2 2
3 3
and then remove Position.TrainingId and Employee.Courseid.
By doing this you make the data much easier to query.
To get things which are not present in one table from another you can use
WHERE NOT EXISTS (SELECT value FROM OtherTable)
or
WHERE NOT IN (SELECT value FROM OtherTable)
However there is a class of queries called subqueries and these are very useful in this circumstance and a very good article on them is here
http://allenbrowne.com/subquery-01.html
(its written for ms access but the synstax and MS SQL rules are exactly the same so dont be put off)
UDF for spliting out entries
Create function [dbo].[atf_BarListToTable]
(#list ntext)
RETURNS #tbl TABLE (ListPosn int IDENTITY(1, 1) NOT NULL,
SString VARCHAR(1028) NOT NULL) AS
BEGIN
DECLARE #pos int
DECLARE #textpos int
DECLARE #ChunkLength smallint
DECLARE #str nvarchar(4000)
DECLARE #tmpstr nvarchar(4000)
DECLARE #leftover nvarchar(4000)
SET #textpos = 1
SET #leftover = ''
WHILE #textpos <= datalength(#list) / 2
BEGIN
SET #ChunkLength = 4000 - datalength(#leftover) / 2
SET #tmpstr = ltrim(#leftover + substring(#list, #textpos, #ChunkLength))
SET #textpos = #textpos + #ChunkLength
SET #pos = charindex('|', #tmpstr)
WHILE #pos > 0
BEGIN
SET #str = substring(#tmpstr, 1, #pos - 1)
INSERT #tbl (SString) VALUES( #str)
SET #tmpstr = ltrim(substring(#tmpstr, #pos + 1, len(#tmpstr)))
SET #pos = charindex('|', #tmpstr)
END
SET #leftover = #tmpstr
END
IF ltrim(rtrim(#leftover)) <> ''
INSERT #tbl (SString) VALUES(#leftover)
RETURN
END
I am seeking guidance using MS SQL cursor or SQL while loop to merge (add, update, and set inactive) rows using single table based on criteria below resulting in seeking the final dataset:
TABLE VIEW (SELECT * FROM TABLE WHERE ENTITY = 123 (#ID)
ENTITY ENTITY_TYPE VALUE STATUS_TYPE
123 1 1 1
123 1 4 1
123 1 9 1
TABLE VIEW (SELECT * FROM TABLE WHERE ENTITY = 456 (#OverrideID)
ENTITY ENTITY_TYPE VALUE STATUS_TYPE
456 1 1 1
456 1 5 1
Final Data Set below:
ENTITY   TYPE VALUE STATUS_TYPE
123 1 1 3
123 1 4 3
123 1 9 3
456 1 1 1
456 1 4 1
456 1 9 1
456 1 1 1
456 1 5 1
-- Check and compare each row
-- IF #OverrideID = #ID (MATCH)
----- Set #ID to inactive keeping copy
-- If #OverrideID != #ID (NOT MATCH)
----- Insert #ID data with #OverrideID (COPY)
----- Set #ID to inactive.
I began writing the following and need help. For reference, #ID = 123 and #OverrideID = 456
DECLARE #ENTITY BIGINT, #ENTITY_TYPE BIGINT, #VALUE BIGINT, #E1 BIGINT, #T1 BIGINT, #V1 BIGINT
DECLARE type_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT * FROM TypeValue WHERE ENTITY = #ID
SET NOCOUNT OFF
OPEN type_cursor
FETCH NEXT FROM type_cursor INTO #OverrideID, #ID, #ENTITY, #ENTITY_TYPE, #VALUE
WHILE (##FETCH_STATUS = 0)
BEGIN
SELECT #ENTITY, #ENTITY_TYPE, #VALUE
IF #VALUE IS NOT NULL
BEGIN
SELECT #T1 = #ENTITY_TYPE, #V1 = #VALUE
END
ELSE
BEGIN
UPDATE TypeValue
SET ENTITY = #OverrideID, ENTITY_TYPE = #T1, VALUE = #V1 WHERE ENTITY = #ID
END
FETCH NEXT FROM type_cursor INTO #OverrideID, #ID, #ENTITY, #ENTITY_TYPE, #VALUE
END
CLOSE type_cursor
DEALLOCATE type_cursor
SET NOCOUNT OFF
That final result set looks like
select entity,entity_type,value,3 status_type
from [table]
where entity = #id
union all
select #override,entity_type,value,status_type
from [table]
where entity = #id
union all
select entity,entity_type,value,status_type
from [table]
where entity = #override
I tried to generate Html from table. And to achieve that, I used function.
TABLE:
LayoutId LayoutDetailsId ParentId DetailSyntax DetailValue
--------------- --------------- --------------- --------------- ---------------
2 15 0 table htmlchild
2 16 15 tbody htmlchild
2 17 16 tr htmlchild
2 18 17 th No.
2 19 17 th Name
2 20 17 th Address
2 21 16 tr htmlchild
2 22 21 td 1
2 23 21 td Asha
2 24 21 td Flamboyan Street
2 25 16 tr htmlchild
2 26 25 td 2
2 27 25 td Jack
2 28 25 td Manggo Street
note that htmlchild in DetailValue is like "HasChild"
FUNCTION:
CREATE FUNCTION FnHtmlGenerator(#layoutId BIGINT, #parentId BIGINT = 0, #prevTopLevelHtml VARCHAR(MAX) = '')
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #currentHtml VARCHAR(MAX);
DECLARE #parentTable TABLE
(
layoutDetailsId BIGINT,
parentId BIGINT,
syntax VARCHAR(50),
val VARCHAR(50)
);
INSERT INTO #parentTable
SELECT
ld.LayoutDetailsId,
ld.ParentId,
ld.DetailSyntax,
ld.DetailValue
FROM Alert.LayoutDetails ld
WHERE ld.ParentId = #parentId
AND ld.LayoutId = #layoutId;
SELECT
#currentHtml = '<' + pt.syntax + '>{0}</' + pt.syntax + '>',
#parentId = pt.layoutDetailsId
FROM #parentTable pt;
SELECT
#prevTopLevelHtml =
CASE CHARINDEX('{0}', #prevTopLevelHtml)
WHEN 0 THEN #currentHtml
ELSE STUFF(#prevTopLevelHtml, CHARINDEX('{0}', #prevTopLevelHtml), 3, #currentHtml)
END;
SELECT
#prevTopLevelHtml =
CASE
(SELECT COUNT(0)
FROM Alert.LayoutDetails ld
WHERE ld.ParentId = #parentId)
WHEN 0 THEN #prevTopLevelHtml
ELSE FnHtmlGenerator(#layoutId, #parentId, #prevTopLevelHtml)
END;
RETURN #prevTopLevelHtml;
END
RESULT:
html
---------------------------------------------------
<table><tbody><tr><td>{0}</td></tr></tbody></table>
The problem is. My function only trace 1 path. the first tr and first td even th is not traced. How to make it trace all path ?
Because when you call
SELECT
#currentHtml = '<' + pt.syntax + '>{0}</' + pt.syntax + '>',
#parentId = pt.layoutDetailsId
FROM #parentTable pt;
... that returns the last row in the table, and assigns that to the variables, so the path is 2/15/16/25/28
You may want to look at the recursive abilities of common table expressions (eg: http://msdn.microsoft.com/en-us/library/ms186243(v=sql.105).aspx) and/or the Hierarchical data type if your database platform supports it (SQL Server 2008+,)