how to merge one row data to one column in sql server - sql

i have one trigger like this:
alter trigger newTrigger
on table2
after insert
as
begin
declare #rowData nvarchar(max)
if exists(select * from inserted)
begin
Set #rowData = (select * from inserted)
end
insert into table1(rowData, date)
values(#rowData, getdate())
end
i want after insert into table2, the inserted record and date insert to table1
but i cant merge the data of row into one column!
------------------table2--------------------
id | name | lname | birth
1 j jj 2000-03-03
-------------------table1 after insert into table2 -----------------
rowData | date
a,j,jj,2000-03-03 2017-05-07

You have to do the conversion and add one by one each column
eg:
Set #rowData = (select cast(col1 as varchar(10)) + cast(col2 as varchar(10)) from inserted)
for your edit with the col names. If the column already is varchar, the only that you have to take care is to avoid the length overflow :
Set #rowData = (select cast((id + ',' + name + ',' + lname + ',' + cast(birth as varchar(12)) ) as varchar(4000)) from inserted)

Related

SQL Loop through tables and columns to find which columns are NOT empty

I created a temp table #test containing 3 fields: ColumnName, TableName, and Id.
I would like to see which rows in the #test table (columns in their respective tables) are not empty? I.e., for every column name that i have in the ColumnName field, and for the corresponding table found in the TableName field, i would like to see whether the column is empty or not. Tried some things (see below) but didn't get anywhere. Help, please.
declare #LoopCounter INT = 1, #maxloopcounter int, #test varchar(100),
#test2 varchar(100), #check int
set #maxloopcounter = (select count(TableName) from #test)
while #LoopCounter <= #maxloopcounter
begin
DECLARE #PropIDs TABLE (tablename varchar(max), id int )
Insert into #PropIDs (tablename, id)
SELECT [tableName], id FROM #test
where id = #LoopCounter
set #test2 = (select columnname from #test where id = #LoopCounter)
declare #sss varchar(max)
set #sss = (select tablename from #PropIDs where id = #LoopCounter)
set #check = (select count(#test2)
from (select tablename
from #PropIDs
where id = #LoopCounter) A
)
print #test2
print #sss
print #check
set #LoopCounter = #LoopCounter + 1
end
In order to use variables as column names and table names in your #Check= query, you will need to use Dynamic SQL.
There is most likely a better way to do this but I cant think of one off hand. Here is what I would do.
Use the select and declare a cursor rather than a while loop as you have it. That way you dont have to count on sequential id's. The cursor would fetch fields columnname, id and tablename
In the loop build a dynamic sql statement
Set #Sql = 'Select Count(*) Cnt Into #Temp2 From ' + TableName + ' Where ' + #columnname + ' Is not null And ' + #columnname <> '''''
Exec(#Sql)
Then check #Temp2 for a value greater than 0 and if this is what you desire you can use the #id that was fetched to update your #Temp table. Putting the result into a scalar variable rather than a temp table would be preferred but cant remember the best way to do that and using a temp table allows you to use an update join so it would well in my opinion.
https://www.mssqltips.com/sqlservertip/1599/sql-server-cursor-example/
http://www.sommarskog.se/dynamic_sql.html
Found a way to extract all non-empty tables from the schema, then just joined with the initial temp table that I had created.
select A.tablename, B.[row_count]
from (select * from #test) A
left join
(SELECT r.table_name, r.row_count, r.[object_id]
FROM sys.tables t
INNER JOIN (
SELECT OBJECT_NAME(s.[object_id]) table_name, SUM(s.row_count) row_count, s.[object_id]
FROM sys.dm_db_partition_stats s
WHERE s.index_id in (0,1)
GROUP BY s.[object_id]
) r on t.[object_id] = r.[object_id]
WHERE r.row_count > 0 ) B
on A.[TableName] = B.[table_name]
WHERE ROW_COUNT > 0
order by b.row_count desc
How about this one - bitmask computed column checks for NULLability. Value in the bitmask tells you if a column is NULL or not. Counting base 2.
CREATE TABLE FindNullComputedMask
(ID int
,val int
,valstr varchar(3)
,NotEmpty as
CASE WHEN ID IS NULL THEN 0 ELSE 1 END
|
CASE WHEN val IS NULL THEN 0 ELSE 2 END
|
CASE WHEN valstr IS NULL THEN 0 ELSE 4 END
)
INSERT FindNullComputedMask
SELECT 1,1,NULL
INSERT FindNullComputedMask
SELECT NULL,2,NULL
INSERT FindNullComputedMask
SELECT 2,NULL, NULL
INSERT FindNullComputedMask
SELECT 3,3,3
SELECT *
FROM FindNullComputedMask

SQL Server query performance: Nested cursors

I have a stored procedure which is selecting some 1-n relations and related data to the referenced column as XML data.
The purpose is to return a record and it's 1-n relations as ONE record with extra data columns, this is done using adding these related data as XML.
Reference table: (TABLE A)
ID NAME VALUE
---------------------
1 Sepehr 1000
2 Sarah 1001
Related table: (TABLE B)
ID Value FK_Value ORDER TITLE
-------------------------------------
1 A 1000 1 t1
2 B 1000 2 t2
3 C 1000 3 t3
I want to get this output:
ID NAME FK_Value Attribs
-----------------------------------------------------
1 Sepehr 1000 <XML><ID>1</ID><ID>2</ID><ID>3</ID></XML>
2 Sarah 1001 null
Actually I was hoping to create a view to do this, but I couldn't and someone told me its not possible using views.
Finally this is the stored procedure I have written - is this a correct approach or are there any other ways?
DECLARE #T1 table (A_ID int,Attribs XML)
DECLARE db_cursorLegendRowsValues CURSOR FOR
SELECT ID, VALUE
FROM A
OPEN db_cursorLegendRowsValues
FETCH NEXT FROM db_cursorLegendRowsValues INTO #loop_ID, #loop_VALUE
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE db_cursorInternal CURSOR FOR
SELECT TITLE, ORDER
FROM B
WHERE FK_Value = #loop_VALUE
OPEN db_cursorInternal
FETCH NEXT FROM db_cursorInternal INTO #tmpTitle, #ORDER
WHILE ##FETCH_STATUS = 0
BEGIN
SET #querySelect = #querySelect + ', MAX(CASE WHEN order = ' + cast(#ORDER as nvarchar(max)) + ' THEN value END) AS [' +REPLACE (#tmpTitle,' ','_') + '] '
FETCH NEXT FROM db_cursorInternal INTO #tmpTitle, #ORDER
END
CLOSE db_cursorInternal
DEALLOCATE db_cursorInternal
SET #query =
' SELECT ' + cast(#loop_ID as nvarchar(max)) +',(
SELECT A.Value,
'
SET #query = #query + STUFF(#querySelect,1,1,'') + ' FROM A
WHERE [A.Value] = ' + cast(#loop_VALUE as nvarchar(max)) + '
FOR XML RAW (''Item''), root (''Items'') , ELEMENTS XSINIL )'
SET #querySelect = ''
--PRINT(#query)
INSERT into #T1 execute (#query )
FETCH NEXT FROM db_cursorLegendRowsValues INTO #loop_ID, #loop_VALUE
END
CLOSE db_cursorLegendRowsValues
DEALLOCATE db_cursorLegendRowsValues
SELECT * FROM #T1
The whole lot can be condensed to a few lines, no cursors needed at all. This wil be useable in a VIEW:
DECLARE #tblA TABLE(ID INT IDENTITY,NAME VARCHAR(100),VALUE INT);
INSERT INTO #tblA VALUES
('Sepehr',1000)
,('Sarah',1001);
DECLARE #tblB TABLE(ID INT IDENTITY,Value VARCHAR(100),FK_Value INT,[ORDER] INT,TITLE VARCHAR(100));
INSERT INTO #tblB VALUES
('A',1000,1,'t1')
,('B',1000,2,'t2')
,('C',1000,3,'t3');
SELECT a.*
,(SELECT ID FROM #tblB AS b WHERE b.FK_Value=a.VALUE FOR XML PATH(''),ROOT('XML'),TYPE) AS Attribs
FROM #tblA AS a
The result
ID NAME VALUE Attribs
1 Sepehr 1000 <XML><ID>1</ID><ID>2</ID><ID>3</ID></XML>
2 Sarah 1001 NULL
It is possible to do this with just one query - you can use a subquery with your select as follows:
select id
, name
, value as fk_value
, (select id from #table_b b
where a.value = b.fk_value
for xml path (''), root ('xml'))
from #table_a a

Insert column value depending on an autoincrement column

I have table in my SQL Server database with following columns
ID | NAME | DOB | APPLICATION NO |
1 | JOHN | 31/05/1986 | KPL\2014\1 |
2 | MARY | 26/04/1965 | KPL\2014\2 |
3 | VARUN | 15/03/1972 | KPL\2014\3 |
Here column ID is an auto increment column and column APPLICATION NO is dependent on ID.
That means APPLICATION NO is the concatenation of KPL\, YEAR and column value of ID.
Then how can I make an insert query?
Why don't you use a computed column ?
I would change the table's definition.
add a "year" column
add an "application_name" column (if it's not always "KPL").
then create your computed column, with the needed fields
alter table <yourTable> add computed_application_name as (application_name + '/' + CAST(<yearColumn> as VARCHAR(4) + '/' + <otherColumn> + CAST(id as VARCHAR(MAX))
Just use a computed column:
alter table t
add application_no as ('KPL' + cast(year(getdate()) as varchar(255)) + cast(id as varchar(255));
It occurs to me that you really want the year when the row was inserted. For that purpose, I would recommend adding a createdat column and then using that instead of getdate():
alter table t add CreatedAt datetime default getdate();
If you have data in the table, then set the value (this is not needed if the table is empty):
update table t set CreatedAt = getdate();
Then define application_no:
alter table t
add application_no as ('KPL' + cast(year(CreatedAt) as varchar(255)) + cast(id as varchar(255));
Simply use a computed column for 'APPLICATION_NO':
create table tbl (
ID int,
NAME varchar(10),
DOB date,
APPLICATION_NO as ('KPL\'+cast(year(dob) as char(4))+'\'+cast(id as varchar))
)
You can further persist and index it as well.
You can create a trigger to run after insert. In your insert, ignore application_no. And your trigger update this column based on ID.
Something like this:
CREATE TRIGGER [TRIGGER_TABLE1] ON TABLE1
AFTER INSERT
AS
BEGIN
UPDATE TABLE1
SET APPLICATION_NO = 'KPL\' + CONVERT(VARCHAR, YEAR(GETDATE())) + '\' + CONVERT(VARCHAR, ID)
WHERE APPLICATION_NO IS NULL
END
EDIT: This way, you should be able to use other columns values as well. APPLICATION_NO just need to accept NULL values. So you control like this what will be updated or not.
Use SCOPE_IDENTITY get the inserted record Id
Declare #Id INT
Insert Into TABLENAME(NAME ,DOB )
Values('Name','1/1/1990')
Set #Id=SCOPE_IDENTITY()
IF(#Id>0)
begin
declare #col varchar(100)=''
set #col= 'KPL\' + CONVERT(varchar(4),YEAR(GETDATE()))+'\' + CONVERT(varchar(4),#Id)
Update TABLENAME
SET APPLICATIONNO= #col
Where ID = #id
end
If you really want to do it by yourself with an insert statement:
assuming that you want to insert data from another table
and TABLE1 is the table you described in your question and TABLE2 would be the table you want to import data from:
DECLARE #MAXID INT
SELECT #MAXID = MAX(ID) FROM TABLE1
INSERT INTO TABLE1
(NAME,DOB,APPLICATION_NO)
SELECT
NAME,
DOB,
'KPL\'
+ CONVERT(CHAR(4),YEAR(GETDATE()) +'\'
+ CONVERT(VARCHAR(25), #MAXID + ROW_NUMBER() OVER (ORDER BY NAME)) AS APPLICATION_NO
FROM TABLE2

Inserting concatenated values in T-SQL

Ok, this is what I am trying to achieve:
My script below is supposed to gather values across three tables and insert them in TO TABLE B in sequence.
There are two columns that are being affected in TABLE B the INDXLONG AND DDLINE.
In The DDLINE row I am attempting to concatenate values from different fields and to store them as one.
My code is below. Please share any insights:
Declare
#nRowCount int,
#Indxlong int,
#hdrLOCAL char(255),
#CR char(255),
#BLDCHKDT DATETIME,
#BLDCHTIME DATETIME,
#hdrline int,
#1strowline int,
#2ndrowline int,
#3rdrowline int,
#BWP char(255),
#CompAcc char(11),
#BankCode char(11),
#BranchNo char(11),
#PayDate datetime,
#Reference char(11),
#TotaAmt numeric(19,5)
#CoName char(11),
#BeneficiaryAcc char(11),
#BenBankBranchCode char(11),
#Salary numeric (19,5),
#BeneficiaryName char(23),
#TransRef char(23),
#outer_c int
SELECT #CompAcc =DDCOIDEN,
#BankCode =DDIMORIG,
#BranchNo =DDIMDEST,
#Reference =DDDESC10,
#CoName =DDIMORNM
FROM TABLE A
Declare ACH SCROLL CURSOR FOR
SELECT T762.DDINDNAM,
T762.DDTRANUM,
T762.DDACTNUM,
T762.DDAMTDLR,
T756.PAYDATE
FROM STATS.dbo.TABLE C T762
LEFT OUTER JOIN STATS.dbo.TABLE D T756 ON (
T762.INDXLONG = T756.INDXLONG
AND T756.INCLPYMT = 1
)
WHERE (T756.INCLPYMT = 1)
AND (T762.DDAMTDLR <> 0)
FOR READ ONLY;
OPEN ACH;
SET NOCOUNT ON;
FETCH FROM ACH INTO #BeneficiaryName,#BenBankBranchCode,#BeneficiaryAcc,#Salary,#paydate
WHILE ##FETCH_STATUS = 0
BEGIN
Select #TotaAmt =SUM(#Salary)
set #hdrline =1
set #1strowline =2
set #2ndrowline =3
set #3rdrowline =9
SELECT #hdrLOCAL = DDLINE FROM TABLE E WHERE INDXLONG =1
SELECT #CR = DDLINE FROM TABLE E WHERE INDXLONG =2
SELECT #BWP = DDLINE FROM TABLE E WHERE INDXLONG =3
BEGIN
INSERT INTO TABLE B (INDXLONG,DDLINE)
VALUES (1,#hdrLOCAL + ',' + #CR + ',' )
SELECT ##IDENTITY
END
BEGIN
INSERT INTO TABLE B (INDXLONG,DDLINE)
VALUES (2,#CompAcc + #BranchNo +','+ #BWP+ ',' + #PayDate +',' + #Reference + ','+#TotaAmt + ','+ #TransRef)
SELECT ##IDENTITY
END
BEGIN
INSERT INTO TABLE B (INDXLONG,DDLINE)
VALUES (3,#BeneficiaryAcc + ',' + #BenBankBranchCode +','+ #BeneficiaryAcc+ ',' + #Salary +',' + #Reference + ','+#TotaAmt + ','+ #TransRef)
SELECT ##IDENTITY
END
FETCH FROM ACH INTO #BeneficiaryName,#BenBankBranchCode,#BeneficiaryAcc,#Salary,#paydate
END
CLOSE ACH
DEALLOCATE ACH
SET NOCOUNT OFF;
This is the error:
Msg 8152, Level 16, State 14, Line 69
String or binary data would be truncated.
The statement has been terminated.
Msg 241, Level 16, State 1, Line 74
Conversion failed when converting date and/or time from character string.
This is the result I am aiming for:
INDXLONG DDLINE ----------- -----------------------------------------------------------------------
1 101001 029 1403200610A094101 AMEN BANK LOVE
2 123456 111 34567 PPDSALARYPAYT140131140117 11234567
3 63206623 0101962706200 0000062709000319614 ADAMS EVE
Cast your dates into varchars/nvarchars if you are going to concatenate them. For examples, #PayDate should be casted like this: cast(PayDate as varchar(20)). Or if you need the date in a specific format, use Convert.

How to get rows having sum equal to given value

There is table contain
ID Qty
----------
1 2
2 4
3 1
4 5
Now if i had to choose rows where sum of Qty equals to 10,
How can i do this ?
like 2+4+1 = 7
but if i add 5 then 12
so ignore 2, then
4+1+5 = 10
How can i achieve this ?
Edit:
I want any possible combination which sums up to gives value.
suppose 7 then any rows which sums up to 7
like wise if 8 then any rows sums up to 8
want row/rows having combination equals to given value.
The problem you want to solve is called the subset sum problem. Unfortunately, it is NP-complete.
This means that, whether you use SQL or any other language to solve it, you will only be able to solve very small instances of the problem, i.e. ones with only a few entries in the table. Otherwise, the runtime will become excessive, since it grows exponentially with the number of rows in the table. The reason for this is that there is essentially no better way of finding the solution than to try all possible combinations.
If an approximate solution is acceptable, there is a polynomial time algorithm, which is described on the Wikipedia page.
If you want it to be exactly always three numbers that add to 10, then this
SELECT
*
FROM
MyTable t1
JOIN
MyTable t2 ON t1.ID <> t2.ID
JOIN
MyTable t3 ON t1.ID <> t3.ID AND t2.ID <> t3.ID
WHERE
t1.Qty + t2.Qty + t3.Qty = 10
If you want 2 or 4 or 5 numbers then you can't really do it in SQL
Edit:
Updated to ignore by ID not Qty
And again: If you want 2 or 4 or 5 numbers then you can't really do it in SQL
When you are dealing with such task in SQL you need to go to the cursors approach.
Cursors let you perform row by row operations and that's what you need, for example:
You want to make groups of where the summed quantity is 10
This are the tasks
select all the table into a temp table #TBL_ALL
loop row by row and when the rows sum up 10, delete from the temp table and insert into a final temp table #TBL_FINAL
do this until the #TBL_ALL sum cant be performed
An example:
Test table:
/****** Object: Table [dbo].[tblExample] Script Date: 06/09/2011 11:25:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tblExample](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Qty] [int] NOT NULL,
CONSTRAINT [PK_tblExample] PRIMARY KEY CLUSTERED
(
[Id] 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
Test Data:
INSERT INTO tblExample SELECT 2;
INSERT INTO tblExample SELECT 4;
INSERT INTO tblExample SELECT 1;
INSERT INTO tblExample SELECT 5;
INSERT INTO tblExample SELECT 5;
INSERT INTO tblExample SELECT 11;
INSERT INTO tblExample SELECT 1;
INSERT INTO tblExample SELECT 2;
INSERT INTO tblExample SELECT 3;
INSERT INTO tblExample SELECT 4;
INSERT INTO tblExample SELECT 7;
INSERT INTO tblExample SELECT 9;
INSERT INTO tblExample SELECT 1;
INSERT INTO tblExample SELECT 2;
Store procedure:
http://pastebin.com/EFeZcKXf
Results:
Grouped table:
ids qty group
12 9 1
7 1 1
11 7 2
9 3 2
4 5 3
5 5 3
2 4 4
10 4 4
14 2 4
Numbers not used:
id qty
1 2
8 2
3 1
13 1
6 11
Hope it helps
SP for those who cant access PasteBin
CREATE PROCEDURE getGroups
(
#groupByQty int, -- grouping number
#numberRuns int -- how many loops
-- usage: getGroups 10, 10
)
AS
SET NOCOUNT ON;
-- declare all variables
DECLARE #rowId int,
#rowQty int,
#rowTotal int,
#groupId int,
#totalRuns int,
#continue bit
-- set up our final temporary table
CREATE TABLE #TBL_COUNT
(
ids NVARCHAR(4000),
qty int,
[group] int
)
-- initializate variable
SET #groupId = 1;
SET #continue = 1;
SET #totalRuns = 0;
SELECT Id, Qty INTO #TBL_ALL FROM tblExample ORDER BY Qty DESC;
WHILE #totalRuns <= #numberRuns
BEGIN
-- declare the cursor
DECLARE Product CURSOR FOR SELECT Id, Qty FROM #TBL_ALL ORDER BY Qty DESC;
OPEN Product;
FETCH Product INTO #rowId, #rowQty;
PRINT ' ';
PRINT '### Run: ' + CAST(#totalRuns AS nvarchar(10)) + ' #################################################################';
PRINT 'Grouping Table by ' + CAST(#groupByQty AS nvarchar(10)) + ' | group id = ' + CAST(#groupId AS nvarchar(10));
-- Retrieve and process the first row
SELECT Top 1 #rowId = Id, #rowQty = Qty FROM #TBL_ALL ORDER BY Qty DESC;
PRINT 'First Row: id = ' + CAST(#rowId AS nvarchar(10)) + ' | qty = ' + CAST(#rowQty AS nvarchar(10));
-- sum it up and see if we have #groupByQty
SELECT #rowTotal = ISNULL(SUM(qty),0) FROM #TBL_COUNT WHERE [group] = #groupId;
PRINT 'Current sum in #TBL_COUNT: #groupId = '+ CAST(#groupId AS nvarchar(10)) +' | #rowTotal = ' + CAST(#rowTotal AS nvarchar(10)) + ' | (#rowTotal + #rowQty) = ' + CAST((#rowTotal + #rowQty) AS nvarchar(10));
IF #rowQty > #groupByQty
BEGIN
PRINT ' x First row has an unused number';
END
ELSE
BEGIN
-- handle result
IF (#rowTotal + #rowQty) = #groupByQty
BEGIN
PRINT '+++ Current sum is ' + CAST(#groupByQty AS nvarchar(10)) + ' +++';
-- save number
INSERT INTO #TBL_COUNT SELECT #rowId, #rowQty, #groupId;
PRINT '### Inserted final # into #TBL_COUNT : id = ' + CAST(#rowId AS nvarchar(10)) + ' | qty = ' + CAST(#rowQty AS nvarchar(10)) + ' | group = ' + CAST(#groupId AS nvarchar(10));
-- remove from table as we use it already
DELETE FROM #TBL_ALL WHERE Id = #rowId;
-- we got 10, let's change our Groupping
SET #groupId = (#groupId + 1);
PRINT 'New group id: ' + CAST(#groupId AS nvarchar(10));
END
ELSE
BEGIN
IF (#rowTotal + #rowQty) < #groupByQty
BEGIN
PRINT '### Inserted into #TBL_COUNT : id = ' + CAST(#rowId AS nvarchar(10)) + ' | qty = ' + CAST(#rowQty AS nvarchar(10)) + ' | group = ' + CAST(#groupId AS nvarchar(10));
-- save number
INSERT INTO #TBL_COUNT SELECT #rowId, #rowQty, #groupId;
-- remove from table as we use it already
DELETE FROM #TBL_ALL WHERE Id = #rowId;
END
ELSE
BEGIN
PRINT ' x Unmatch number, will handle this latter';
END
END
END
-- start the main processing loop
WHILE ##Fetch_Status = 0
BEGIN
FETCH Product INTO #rowId, #rowQty;
PRINT '##Fetch_Status = ' + CAST(##Fetch_Status AS nvarchar(100));
IF ##Fetch_Status < 0
BEGIN
BREAK
END
-- we have the values of our row, let's use them
PRINT 'Fetched Row: id = ' + CAST(#rowId AS nvarchar(10)) + ' | qty = ' + CAST(#rowQty AS nvarchar(10));
-- sum it up and see if we have #groupByQty
SELECT #rowTotal = ISNULL(SUM(qty),0) FROM #TBL_COUNT WHERE [group] = #groupId;
PRINT 'Current sum in #TBL_COUNT: #groupId = '+ CAST(#groupId AS nvarchar(10)) +' | #rowTotal = ' + CAST(#rowTotal AS nvarchar(10)) + ' | (#rowTotal + #rowQty) = ' + CAST((#rowTotal + #rowQty) AS nvarchar(10));
-- handle result
IF (#rowTotal + #rowQty) = #groupByQty
BEGIN
PRINT '+++ Current sum is ' + CAST(#groupByQty AS nvarchar(10)) + ' +++';
-- save number
INSERT INTO #TBL_COUNT SELECT #rowId, #rowQty, #groupId;
PRINT '### Inserted final # into #TBL_COUNT : id = ' + CAST(#rowId AS nvarchar(10)) + ' | qty = ' + CAST(#rowQty AS nvarchar(10)) + ' | group = ' + CAST(#groupId AS nvarchar(10));
-- remove from table as we use it already
DELETE FROM #TBL_ALL WHERE Id = #rowId;
-- we got 10, let's change our Groupping
SET #groupId = (#groupId + 1);
PRINT 'New group id: ' + CAST(#groupId AS nvarchar(10));
-- start again
BREAK;
END
ELSE
BEGIN
IF (#rowTotal + #rowQty) < #groupByQty
BEGIN
PRINT '### Inserted into #TBL_COUNT : id = ' + CAST(#rowId AS nvarchar(10)) + ' | qty = ' + CAST(#rowQty AS nvarchar(10)) + ' | group = ' + CAST(#groupId AS nvarchar(10));
-- save number
INSERT INTO #TBL_COUNT SELECT #rowId, #rowQty, #groupId;
-- remove from table as we use it already
DELETE FROM #TBL_ALL WHERE Id = #rowId;
END
ELSE
BEGIN
PRINT ' x Unmatch number, will handle this latter';
END
END
END -- END WHILE ##Fetch_Status = 0
SET #totalRuns = #totalRuns + 1;
-- Close and dealocate
CLOSE Product;
DEALLOCATE Product;
END -- END WHILE totalRuns <= #numberRuns
-- let's sum our last group and remove it if it's not #groupByQty
SELECT #rowTotal = ISNULL(SUM(qty),0) FROM #TBL_COUNT WHERE [group] = #groupId;
IF #rowTotal <> #groupByQty
BEGIN
SET IDENTITY_INSERT #TBL_ALL ON
INSERT INTO #TBL_ALL (Id, Qty) SELECT Ids, Qty FROM #TBL_COUNT WHERE [group] = #groupId;
DELETE FROM #TBL_COUNT WHERE [group] = #groupId;
END
SET NOCOUNT OFF;
-- Show and Delete temp tables
SELECT * FROM #TBL_COUNT;
SELECT * FROM #TBL_ALL;
DROP TABLE #TBL_COUNT;
DROP TABLE #TBL_ALL;
P.S. I'm not a SQL Professional, so bear with me if I did something weird, and keep in mind that this is a performance waste, maybe someone can use the the Loop without Cursors, more in this page
If u add always 3 numbers its like gbn said, if not then u have to check every combination of ur rows which gives u 2 to the number_of_rows power cobinations and i dont see how can it be done on sql in one query. If u use loop in sql sure its possible but u should find some good algorithm to finish this task.