Sql query checking condition before insert row - sql

I have a table called dbo.Tbl_ActivityInformations and the data look like
Activityid activitymaxcount Activityusedcount
1 10 9
2 10 7
3 15 15
And another table called Tbl_AttendeeInformations and the data look like
AttendedID AssID ActivityID
13 123456 1,2
14 123457 1,3
In the Tbl_AttendeeInformations table data will be inserted as new row from page and in the ActivityInformations table Activityusedcount column incremented by one for appropriate activityID.
Now I want to check before inserting a row into AttendeeInformations that Activityusedcount < activitymaxcount using ActivityID. If the condition is satisfied then only it will allow to insert otherwise it should rollback. I have function named SplitString to split ActivityID in Tbl_AttendeeInformations.
This is the code for SplitString
create FUNCTION dbo.SplitString(#FormattedString varchar(8000),#Delimitter char(1))
returns #retResults TABLE(Value varchar(8000),Rownumber int)
as
BEGIN
DECLARE #SearchString as varchar(8000)
DECLARE #AssignString as varchar(8000)
DECLARE #Index int
DECLARE #Count int
set #SearchString = #FormattedString
set #AssignString= ''
set #Count = 0
while(len(#SearchString) > 0 )
begin
SET #Index = CHARINDEX(#Delimitter,#SearchString, 0)
set #Count = #Count + 1
if #Index = 0
begin
INSERT INTO #retResults
values( #SearchString,#Count)
set #SearchString = ''
continue
end
set #AssignString = SUBSTRING(#SearchString,1, #Index - 1 )
INSERT INTO #retResults values
(#AssignString,#Count)
SET #SearchString = (select SUBSTRING(#SearchString, #Index + 1, LEN(#SearchString) - #Index ))
end
return
END
Please do help.

Pseudocode to show an idea:
INSERT INTO AttendeeInformations
SELECT act.*
FROM ActivityInformations act
INNER JOIN AttendeeInformations at ON act.ActivityID = at.ActivityID
WHERE act.Activityusedcount < act.activitymaxcount

Related

Comma Separated List from SQL Grouping

I'm trying to build comma separated list per group in sql,
As am using Parallel Data Warehouse i need to do this without using FOR XML or recursive function ( not supported ).
any other way to achieve this ?
Input:
ID Value
1 2
1 3
1 4
2 1
2 10
Output:
ID List
1 2,3,4
2 1,10
This will not perform well at all so I recommend you use some other solution (like a SQL Server linked server to PDW) if you need performance. But I believe this should work on PDW:
declare #ID int = (select min(ID) from tbl);
declare #Value int = -1;
declare #concat varchar(8000) = '';
create table #tmp (
ID int,
[concat] varchar(8000)
)
with (distribution=hash(ID), location=user_db);
while #ID is not null
begin
set #Value = (select min([Value]) from tbl where ID = #ID and [Value]>#Value);
if #Value is not null
set #concat = #concat + case when #concat = '' then '' else ',' end + cast(#Value as varchar(8000));
else
begin
insert #tmp (ID, [concat])
values (#ID, #concat);
set #ID = (select min(ID) from tbl where ID > #ID);
set #Value = -1;
set #concat = '';
end
end
select * from #tmp;
drop table #tmp;

The best method to update every row in SQL Server

I have code like this to create random table: (http://dba.fyicenter.com/faq/sql_server/Creating_a_Large_Table_with_Random_Data_for_Indexes.html)
-- Create a table with primary key
CREATE TABLE fyi_random
(
id INT,
rand_integer INT,
rand_number numeric(18,9),
rand_datetime DATETIME,
rand_string VARCHAR(80)
);
-- Insert rows with random values
DECLARE #row INT;
DECLARE #string VARCHAR(80), #length INT, #code INT;
SET #row = 0;
WHILE #row < 100000
BEGIN
SET #row = #row + 1;
-- Build the random string
SET #length = ROUND(80*RAND(),0);
SET #string = '';
WHILE #length > 0
BEGIN
SET #length = #length - 1;
SET #code = ROUND(32*RAND(),0) - 6;
IF #code BETWEEN 1 AND 26
SET #string = #string + CHAR(ASCII('a')+#code-1);
ELSE
SET #string = #string + ' ';
END
-- Ready for the record
SET NOCOUNT ON;
INSERT INTO fyi_random
VALUES (#row,
ROUND(2000000*RAND()-1000000,0),
ROUND(2000000*RAND()-1000000,9),
CONVERT(DATETIME, ROUND(60000*RAND() - 30000, 9) ),
#string)
END
PRINT 'Rows inserted: '+CONVERT(VARCHAR(20),#row);
GO
I want to update every row (for example update column rand_string with some new random string). What is the best method? When I'm trying to do this by while loop performance decreases with increasing rows:
...
SET NOCOUNT ON;
UPDATE random_data
SET rand_string = #string
WHERE id = #row;
I also tried to use cursor statement and it's better but why while loop is so slow? And is there another way to do this better?
If you want to update every row in a table then just omit the where clause in the update statement.

remove numeric values in data using sql

my data is :
Id Case ID#
1. QCCR1A105369, QCCR1A104986 ,QCCR1A103717
2. QCIM1A106902,4613410733 QCIM1A106902; 4613344523 QCIM1A105842; 4614004212 QCIM1A106580; 4614060189 QCIM1A106676
3. QCCR1D93616, QCCR1D92488, QCCR1D58461
4. QCCR1B40216 .... ,QCCR1B39080, QCCR1B40216, QCCR1B39745, QCCR1B38463 , QCCR1B38618, QCCR1B38619, QCCR1B38620, QCCR1B38621, QCCR1B38622, QCCR1B38465, QCCR1B38623
5. QCCR2A30221 QCCR2A30223 QCCR2A30222 QCIM2A30416
My output will be Id 1,3,4,5. I want only that rows, which have starting value QC not any numeric value. For ID 2 you can see there are some numeric values, please tell me how can I achieve it.
You could use a table valued function to split your value by a delimiter like this:
CREATE FUNCTION [dbo].[Split]
(
#ItemList NVARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #ItemTable TABLE (Item VARCHAR(250))
AS
BEGIN
DECLARE #tempItemList NVARCHAR(MAX)
SET #tempItemList = #ItemList
DECLARE #i INT
DECLARE #Item NVARCHAR(4000)
SET #i = CHARINDEX(#delimiter, #tempItemList)
WHILE (LEN(#tempItemList) > 0)
BEGIN
IF #i = 0
SET #Item = #tempItemList
ELSE
SET #Item = LEFT(#tempItemList, #i - 1)
INSERT INTO #ItemTable(Item) VALUES(#Item)
IF #i = 0
SET #tempItemList = ''
ELSE
SET #tempItemList = RIGHT(#tempItemList, LEN(#tempItemList) - #i)
SET #i = CHARINDEX(#delimiter, #tempItemList)
END
RETURN
END
Then this query returns the expected result:
SELECT t.*
FROM dbo.TableName t
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.Split(t.CaseID, ',') split
WHERE NOT LEFT(LTRIM(split.Item), 2) = 'QC'
OR ISNUMERIC(split.Item) = 1
)
Demo with your sample data. But in general you should avoid multiple values in one column. Instead store it in separate rows in a linked table. That's called database normalization.

return separate character from a string

How to return all the characters from a string and count it in sql.
if the string is "how are you"
it should return
char count
2
h 1
o 2
w 1
a 1
r 1
e 1
y 1
u 1
You can use this script. It will give you exactly what you need.
This one counts just the letters in the string.
declare #c int
declare #ch varchar(10)
declare #str varchar(max)
set #str = 'how are you'
declare #letter int
declare #i int
set #i = 1
create table #tbl(ch varchar(10), cnt int)
while (#i <= len(#str))
begin
set #letter = 0
set #ch = substring(#str, #i, 1)
select #c = count(*) from #tbl
where ch = #ch
if ( (#ch >= 'a' and #ch <= 'z') or (#ch >= 'A' and #ch <= 'Z') )
begin
set #letter = 1
end
if (#c = 0)
begin
if (#letter = 1)
begin
insert into #tbl (ch, cnt) values (#ch, 1)
end
end
else
begin
update #tbl set cnt = cnt + 1 where ch = #ch
end
set #i = #i + 1
end
select * from #tbl
drop table #tbl
And if you want to count all chars (not just letters),
this makes it even easier. Use this script.
declare #c int
declare #ch varchar(10)
declare #str varchar(max)
set #str = 'how are you'
declare #i int
set #i = 1
create table #tbl(ch varchar(10), cnt int)
while (#i <= len(#str))
begin
set #ch = substring(#str, #i, 1)
select #c = count(*) from #tbl
where ch = #ch
if (#c = 0)
begin
insert into #tbl (ch, cnt) values (#ch, 1)
end
else
begin
update #tbl set cnt = cnt + 1 where ch = #ch
end
set #i = #i + 1
end
select * from #tbl
drop table #tbl
You can use a customer tsql function, see http://gallery.technet.microsoft.com/scriptcenter/T-SQL-Script-to-Split-a-308206f3.
And you can make a query solve your issue using group by and count statements ?
This will return the result set you have requested. It does this by taking each letter and adding it to a new row within a temporary table and then querying the results to return the counts for each occurrence of the character.
DECLARE #individual CHAR(1);
DECLARE #text NVARCHAR(200)
SET #text = 'how are you';
IF OBJECT_ID('tempdb..#tmpTable') IS NOT NULL
DROP TABLE #tmpTable
CREATE TABLE #tmpTable (letter char(1));
WHILE LEN(#text) > 0
BEGIN
SET #individual = SUBSTRING(#text, 1, 2)
INSERT INTO #tmpTable (letter) VALUES (#individual);
SET #text = SUBSTRING(#text, 2, LEN(#text))
END
SELECT letter, COUNT(*) AS [count]
FROM #tmpTable
GROUP BY letter;

Select a specific number from a row in sql query

I want to select a SQL Query for only "09xxxxxxxxx" from below table :
021-77083709 - 09125800327
09123301673 22514057
09121964217 09332712035
Its might be anywhere in the row and I want to select these numbers. This mean "09" + 9 character after that.
For Example in overhead rows, select these numbers :
09125800327
09123301673
09121964217
09332712035
My Table
http://upload.tehran98.com/upme/uploads/33a59e81d6d51d311.jpg
Thanks
This will get you part of the way there...
SELECT SUBSTRING(tbl.columnName,
PATINDEX('%09[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',
tbl.ColumnName), 11) FirstOccurrance
FROM TableName tbl
WHERE tbl.columnName LIKE '%09[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%'
This will only extract the first occurrence of the pattern within a column,
also the pattern matching is pretty limited.
By the way in your example is 09 + 9 characters not 10
Here is a function that can be used to extract all matching values in a column as a csv string
CREATE FUNCTION dbo.FilterValues
(
#OriginalValue NVARCHAR(2000)
)
RETURNS NVARCHAR(2000)
AS
BEGIN
DECLARE #IDX INT = PATINDEX('%09[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',
#OriginalValue);
DECLARE #Temp NVARCHAR(4000) = #OriginalValue;
DECLARE #Result NVARCHAR(4000) = '';
WHILE ( #IDX IS NOT NULL
AND #IDX > 0
)
BEGIN
SET #Result = #Result + SUBSTRING(#Temp, #IDX, 11);
SET #Temp = SUBSTRING(#Temp, #IDX + 11, LEN(#Temp) - 11);
SET #IDX = PATINDEX('%09[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',
#Temp);
IF ( #IDX IS NOT NULL
AND #IDX > 0
)
BEGIN
SET #Result = #Result + ',';
END
END
RETURN #Result;
END
Here is an example on how to use the query with the function
SELECT dbo.FilterValues(tbl.ColumnName) MatchedValues
FROM TableName tbl
WHERE tbl.columnName LIKE '%09[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%'