How to insert data multiple times in a table (SQL) - sql

I have 3 tables as follows:
DXBusinessPolicy_Policy
ID
Code
Name
1
COMBO.2103001
[Giá nền] T9/2020 #1
2
IPTV-0121.002
[Giá nền] T8/2020 #1
DXBusinessPolicy_Service
ID
Code
Name
1
INT
Internet
2
IPTV
IPTV
3
CMR
Camera
4
FSAFE
Fsafe
DXBusinessPolicy_PolicyService
ID
PolicyID
ServiceID
1
1
1
2
1
2
Here is my stored procedure:
CREATE PROCEDURE InsertPolicyService
#id int,
#services varchar(1000) //This is Service Name
AS
BEGIN
INSERT INTO dbo.DXBusinessPolicy_PolicyService (PolicyID, ServiceID)
SELECT
#id,
(SELECT dbo.DXBusinessPolicy_Service.ID
FROM dbo.DXBusinessPolicy_Service
WHERE dbo.DXBusinessPolicy_Service.Code IN (SELECT VALUE FROM string_split(#services, ',')))
END
EXEC InsertPolicyService 2, 'FSAFE,CMR'
I want to insert Policy ID 2 with service named FSAFE and CMR into table DXBusinessPolicy_PolicyService.
I tried to execute this stored procedure, but I get this error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
My expectation is:
DXBusinessPolicy_PolicyService
ID
PolicyID
ServiceID
1
1
1
2
1
2
3
2
3
4
2
4

Your inner sub-query returns multiple results, which isn't possible when its a sub-query. However you don't need that many queries, just the one:
INSERT INTO dbo.DXBusinessPolicy_PolicyService (PolicyID, ServiceID)
SELECT #id, dbo.DXBusinessPolicy_Service.ID
FROM dbo.DXBusinessPolicy_Service
WHERE dbo.DXBusinessPolicy_Service.Code IN (
SELECT VALUE FROM string_split(#services,','))
);

Related

Stored Procedure expected multiple rows

Expecting duplicate row with different output in the last column.
Here's my Stored Procedure query
SELECT
Name = SELECT ......
Mobile = SELECT .....
Title = SELECT .....
Developer = (SELECT Description FROM ParameterDeveloper WHERE Id IN (SELECT WorkId FROM Company WHERE Id = Records.ApplicationId)
FROM Records
Here's my Records Table
ApplicationId
Name
100
Sky
300
Sam
400
Luke
Here's my ParameterDeveloper Table
Id
Description
100
Oracle
100
Ibm
200
Salesforce
Here's my Company Table
Id
WorkId
100
100
200
200
300
300
Expected result -
Name
Developer
Sky
Oracle
Sky
Ibm
My Error is:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
your data
CREATE TABLE Records (
ApplicationId INTEGER NOT NULL
,Name VARCHAR(100) NOT NULL
);
INSERT INTO Records
(ApplicationId,Name) VALUES
(100,'Sky'),
(300,'Sam'),
(400,'Luke');
CREATE TABLE ParameterDeveloper (
Id INTEGER NOT NULL
,Description VARCHAR(100) NOT NULL
);
INSERT INTO ParameterDeveloper
(Id,Description) VALUES
(100,'Oracle'),
(100,'Ibm'),
(200,'Salesforce');
CREATE TABLE Company (
Id INTEGER NOT NULL
,WorkId INTEGER NOT NULL
);
INSERT INTO Company
(Id,WorkId) VALUES
(100,100),
(200,200),
(300,300);
your query
select Name,Description
from Records R
JOIN Company C
ON C.Id=R.ApplicationId
JOIN ParameterDeveloper P
ON P.Id=R.ApplicationId
dbfiddle

Removing Duplicate Sets of Rows

Data
CREATE TABLE #tbl_LinkedInvoices(
InvoiceNbr varchar(50)
, AssociatedInvoiceNbr varchar(50)
, RowNbr int
, AssociatedRowNbr int
)
INSERT INTO #tbl_LinkedInvoices(
InvoiceNbr, AssociatedInvoiceNbr, RowNbr, AssociatedRowNbr)
VALUES
('A0001', 'A1001', 1, 4),
('A0002', 'A2002', 2, 5),
('A0002', 'A3002', 3, 6),
('A1001', 'A0001', 4, 1),
('A2002', 'A0002', 5, 2),
('A3002', 'A0002', 6, 3)
SELECT * FROM #tbl_LinkedInvoices
Challenge/Goal
tbl_LinkedInvoices is meant to identify the AssociatedInvoiceNbrs b an InvoiceNbr a is linked to. As such, a set can appear multiple times in the table since (a, b) = (b,a). To address these reappearances RowNbr and AssociatedRowNbr fields are added to give grouped sequences.
With the identified duplicate rows, remove duplicate row, preserving a single unique record in the table. Current script yields error, expect there might be a better way to write the query.
Script
Use a counter to check if the duplicate row still exists, if it does delete that row, till FALSE.
DECLARE #RowCounter int
DECLARE #RemoveRow int
SET #RowCounter = 1
IF EXISTS (SELECT
RowNbr
FROM #tbl_LinkedInvoices WHERE RowNbr = (SELECT AssociatedRowNbr FROM #tbl_LinkedInvoices)
)
BEGIN
SET #RemoveRow = (SELECT RowNbr FROM #tbl_LinkedINvoices
WHERE RowNbr = (
SELECT AssociatedRowNbr FROM #tbl_LinkedInvoices WHERE RowNbr =#RowCounter ))
BEGIN
DELETE FROM #tbl_LinkedInvoices
WHERE
RowNbr = #RemoveRow
END
BEGIN
SET #RowCounter = #RowCounter + 1
END
END
Error
Msg 512, Level 16, State 1, Line 212
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
If I followed you correctly, you can perform the deletion of "mirror" records in a single statement, without using the additional computed columns:
delete t
from #tbl_LinkedInvoices t
where exists (
select 1
from #tbl_LinkedInvoices t1
where
t1.AssociatedInvoiceNbr = t.InvoiceNbr
and t1.InvoiceNbr = t.AssociatedInvoiceNbr
and t1.AssociatedInvoiceNbr > t.AssociatedInvoiceNbr
)
This removes mirror records while retaining the one whose InvoiceNbr is smaller than AssociatedInvoiceNbr.
Demo on DB Fiddle with your sample data.
After the delete statement is executed, the content of the table is:
InvoiceNbr | AssociatedInvoiceNbr | RowNbr | AssociatedRowNbr
:--------- | :------------------- | -----: | ---------------:
A0001 | A1001 | 1 | 4
A0002 | A2002 | 2 | 5
A0002 | A3002 | 3 | 6

How can I create 1 ID for a group of customers in a column?

I have a list of customers who have different contracts with my service company.
Sometimes we can have different customers per contracts. Example:
Karen and her boyfriend Will have a contract.
Sometimes a group of customers can have different contracts. Example: Karen and Will have multiple contracts with me.
Here is the table:
idCustomer idContract NameCust
-----------------------------------------
1 A Karen
1 B Will
2 A Karen
2 B Will
3 C Steph
4 C Peter
But because Karen and Will can have multiple contracts, I want a unique id for them and other group of customers. Result table I want:
idCustomer idContract NameCust Customer_GroupID
-----------------------------------------------------
1 A Karen 1
1 B Will 1
2 A Karen 1
2 B Will 1
3 C Steph 2
4 C Peter 2
I'm stuck because I tried different things that doesn't give me the result I need. I find in the forum someone who used Dense_Rank function but here is the result:
SELECT
RANK() OVER (ORDER BY idCustomers) AS Customer_GroupID,
IdCustomers,
IdContract
FROM
Table
Here is the result:
Cust_GroupID idCustomer idContract
--------------------------------------
1 1 A
2 1 B
1 2 A
2 2 B
3 3 C
3 4 C
I even tried to use multiple select, not exists but nothing.
It seem that I have understood your requirement. Still you should throw little more sample data to make it absolute clear to all. Append few more varied sample data in existing one.
You should test with different sample data and let me know if its not working.
Sample Data,
create table #test(idCustomer int,idContract varchar(50) , NameCust varchar(50))
insert into #test (idCustomer ,idContract , NameCust ) VALUES
(1,'A','Karen')
,(1,'B','Will' )
,(2,'A','Karen')
,(2,'B','Will' )
,(3,'C','Steph')
,(4,'C','Peter')
Method 1- SET BASED Approach,
;with CTE as
(
select *
,ROW_NUMBER()over(order by idCustomer)rn
from #test
)
,CTE1 as
(
select t.id,t.idContract,t.NameCust
, isnull(t1.idCustomer,t.idCustomer)customerGroupID
from CTE t
outer apply(
select top 1 idCustomer
from CTE t1
where t1.id< t.id
and((t.idCustomer=t1.idCustomer)
or (t.idContract=t1.idContract))
order by t1.id
)t1
)
,CTE2 AS(
select *
,DENSE_RANK()OVER( order by customerGroupID )Customer_GroupID
from CTE1
)
select * from CTE2
Method 2- RBAR (using cursor),
create table #test1(id int identity(1,1),idCustomer int
,idContract varchar(50) , NameCust varchar(50),customer_Groupid int)
insert into #test1 (idCustomer ,idContract
, NameCust,customer_Groupid )
select idCustomer ,idContract , NameCust,null
from #test
DECLARE #idCustomer INT
DECLARE #idContract varchar(50)
DECLARE #id INT
declare #customer_Groupid int
DECLARE #getCustomer CURSOR
SET #getCustomer = CURSOR FOR
SELECT id, idCustomer,idContract
FROM #test1
OPEN #getCustomer
FETCH NEXT
FROM #getCustomer INTO #id, #idCustomer,#idContract
WHILE ##FETCH_STATUS = 0
BEGIN
select top 1 #customer_Groupid=customer_Groupid
from #test1 where id<#id order by id desc
if not exists(select 1 from #test1 where id<#id
and (idCustomer=#idCustomer or idContract=#idContract))
BEGIN
select top 1 #customer_Groupid=customer_Groupid
from #test1 where id<#id order by id desc
if(#customer_Groupid is not null)
set #customer_Groupid=#customer_Groupid+1
end
if(#customer_Groupid is null)
set #customer_Groupid=1
update #test1 set customer_Groupid=#customer_Groupid where id=#id
FETCH NEXT
FROM #getCustomer INTO #id, #idCustomer,#idContract
END
CLOSE #getCustomer
DEALLOCATE #getCustomer
select * from #test1
drop table #test1
drop table #test
There seems to be a need to create an interim table of NameCustGroup like
NameCustList idCustomer idContract
Karen,Will 1 A,B
Karen,Will 2 A,B
Peter,Steph 3 C
Peter,Steph 4 C
And then use that to create
Customer_GroupID idCustomer idContract
1 1 A,B
1 2 A,B
2 3 C
2 4 D
The interim table seems hardest, because the NameCustList needs to be formed either by Common idCustomer or Common idContract. This is a work in progress... ...

SQL Server find unique combinations

I have a table
rate_id service_id
1 1
1 2
2 1
2 3
3 1
3 2
4 1
4 2
4 3
I need to find and insert in a table the unique combinations of sevice_ids by rate_id...but when the combination is repeated in another rate_id I do not want it to be inserted
In the above example there are 3 combinations
1,2 1,3 1,2,3
How can I query the first table to get the unique combinations?
Thanx!
Try doing something like this:
DECLARE #TempTable TABLE ([rate_id] INT, [service_id] INT)
INSERT INTO #TempTable
VALUES (1,1),(1,2),(2,1),(2,3),(3,1),(3,2),(4,1),(4,2),(4,3)
SELECT DISTINCT
--[rate_id], --include if required
(
SELECT
CAST(t2.[service_id] AS VARCHAR) + ' '
FROM
#TempTable t2
WHERE
t1.[rate_id] = t2.[rate_id]
ORDER BY
t2.[rate_id]
FOR XML PATH ('')
) AS 'Combinations'
FROM
#TempTable t1
I put the values in a table variable just for ease of testing the SELECT query.

How do you find a missing number in a table field starting from a parameter and incrementing sequentially?

Let's say I have an sql server table:
NumberTaken CompanyName
2 Fred 3 Fred 4 Fred 6 Fred 7 Fred 8 Fred 11 Fred
I need an efficient way to pass in a parameter [StartingNumber] and to count from [StartingNumber] sequentially until I find a number that is missing.
For example notice that 1, 5, 9 and 10 are missing from the table.
If I supplied the parameter [StartingNumber] = 1, it would check to see if 1 exists, if it does it would check to see if 2 exists and so on and so forth so 1 would be returned here.
If [StartNumber] = 6 the function would return 9.
In c# pseudo code it would basically be:
int ctr = [StartingNumber]
while([SELECT NumberTaken FROM tblNumbers Where NumberTaken = ctr] != null)
ctr++;
return ctr;
The problem with that code is that is seems really inefficient if there are thousands of numbers in the table. Also, I can write it in c# code or in a stored procedure whichever is more efficient.
Thanks for the help
Fine, if this question isn't going to be closed, I may as well Copy and paste my answer from the other one:
I called my table Blank, and used the following:
declare #StartOffset int = 2
; With Missing as (
select #StartOffset as N where not exists(select * from Blank where ID = #StartOffset)
), Sequence as (
select #StartOffset as N from Blank where ID = #StartOffset
union all
select b.ID from Blank b inner join Sequence s on b.ID = s.N + 1
)
select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence))
You basically have two cases - either your starting value is missing (so the Missing CTE will contain one row), or it's present, so you count forwards using a recursive CTE (Sequence), and take the max from that and add 1
Tables:
create table Blank (
ID int not null,
Name varchar(20) not null
)
insert into Blank(ID,Name)
select 2 ,'Fred' union all
select 3 ,'Fred' union all
select 4 ,'Fred' union all
select 6 ,'Fred' union all
select 7 ,'Fred' union all
select 8 ,'Fred' union all
select 11 ,'Fred'
go
I would create a temp table containing all numbers from StartingNumber to EndNumber and LEFT JOIN to it to receive the list of rows not contained in the temp table.
If NumberTaken is indexed you could do it with a join on the same table:
select T.NumberTaken -1 as MISSING_NUMBER
from myTable T
left outer join myTable T1
on T.NumberTaken= T1.NumberTaken+1
where T1.NumberTaken is null and t.NumberTaken >= STARTING_NUMBER
order by T.NumberTaken
EDIT
Edited to get 1 too
1> select 1+ID as ID from #b as b
where not exists (select 1 from #b where ID = 1+b.ID)
2> go
ID
-----------
5
9
12
Take max(1+ID) and/or add your starting value to the where clause, depending on what you actually want.