Stored Procedure expected multiple rows - sql

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

Related

SQL Query Optimization to retrieve non-null entries

Need help in optimizing SQL query, I have figured a way to solve the problem by using UNIONALL, but my worry is that performance will be impacted as the record set is huge in production env.
I have a table of records in below format, I need help in retrieving the non-null entries if available otherwise pick the null entries.
In the below case; Query should exclude RowIds 1,7 and retrieve everything else, i.e because there are non-null entries for that combination.
RowID
UniqueID
TrackId
1
325
NULL
2
325
8zUAC
3
325
99XER
4
427
NULL
5
632
2kYCV
6
533
NULL
7
774
NULL
8
774
94UAC
--UNIONALL Command
SELECT A.* FROM
( SELECT * FROM [MY_PKG].[TEMP] WHERE TRACKID is not null) A
WHERE A.UNIQUEID in
( SELECT UNIQUEID FROM [MY_PKG].[TEMP] WHERE TRACKID is null
)
UNION ALL
SELECT B.* FROM
( SELECT * FROM [MY_PKG].[TEMP] WHERE TRACKID is null) B
WHERE B.UNIQUEID not in
( SELECT UNIQUEID FROM [MY_PKG].[TEMP] WHERE TRACKID is not null
)
Temp Table Creation Scrip
CREATE TABLE MY_PKG.TEMP
( UNIQUEID varchar(3),
TRACKID varchar(5)
);
INSERT INTO MY_PKG.TEMP
( UNIQUEID, TRACKID)
VALUES
('325',null),
('325','8zUAC'),
('325','99XER'),
('427',null),
('632','2kYCV'),
('533','2kYCV'),
('774',null),
('774','94UAC')
You can use the NOT EXISTS operator with a correlated subquery:
SELECT * FROM TEMP T
WHERE TRACKID IS NOT NULL
OR (TRACKID IS NULL
AND NOT EXISTS(
SELECT 1 FROM TEMP D
WHERE D.UNIQUEID = T.UNIQUEID AND
D.TRACKID IS NOT NULL)
)
See demo

Merge rows based on values in 2 tables

I have a table with travel details. Details are getting saved in distributed manner. I need to merge the rows based on Source and Destination. My Source is A and Final Destination is D, I need to merge all the 3 rows into 1 with sum of time and distance.
Table1:Trip details
CarID
Source
Destination
Distance
Time
1
A
B
10
1
1
B
C
20
2
1
C
D
30
3
Table2: TravelPlan
CarID
Source
Destination
1
A
D
Output Needed:
Table 3:
CarID
Source
Destination
Distance
Time
1
A
D
60
6
I tried using Concatenate but not able to do based on conditions. Not sure how to combine rows of one table based on values of another.
your Data
DECLARE #TripDetails TABLE (
CarID INT NOT NULL
,Source VARCHAR(20) NOT NULL
,Destination VARCHAR(20) NOT NULL
,Distance INT NOT NULL
,Time INT NOT NULL
);
INSERT INTO #TripDetails
(CarID,Source,Destination,Distance,Time)
VALUES
(1,'A','B',10,1),
(1,'B','C',20,2),
(1,'C','D',30,3);
DECLARE #TravelPlan TABLE (
CarID INT NOT NULL
,Source VARCHAR(20) NOT NULL
,Destination VARCHAR(20) NOT NULL
);
INSERT INTO #TravelPlan
(CarID,Source,Destination) VALUES
(1,'A','D');
what you need are Subquery and join and SUM. your query
SELECT TP.carID,
       TP.Source,
       TP.Destination,
       TD.Distance,
       TD.Time
FROM   (select carID,
               Sum(Distance) Distance,
               Sum(Time)     Time
        FROM   #TripDetails
GROUP BY carID) TD
       JOIN #TravelPlan TP
         ON TD.carID = TP.carID
Fiddle

How to insert data multiple times in a table (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,','))
);

Find Unmatch record 2 table with where condition apply and record show from 1 table

class table
class_code varchar(50)
timing varchar(50)
emp_id varchar(50)
employee table
i_id int
emp_id varchar(20)
name varchar(50)
We Have 2 tables 1 is employee and other is class
we have 4 records in employee table where emp_id=as-1,as-2,as-3,as-4
we have 2 records in class table with emp_id = as-1 or as-3 and timing= '3-4'
We select those record from employee table who available/free at timing='3-4' like as-2 or as-3 because as-1 or as-3 is already in class table in timing at 3-4
You have not told us a great deal and the indicated data may not be fully representative. Both of these will return employee 2 and 4 (& both will work in MySQL or MSsql):
SELECT
e.*
FROM employee e
LEFT JOIN class c
ON e.emp_id = c.emp_id
WHERE (c.timing <> '3-4'
OR c.timing IS NULL)
;
SELECT
*
FROM employee
WHERE NOT EXISTS (
SELECT 1
FROM class
WHERE timing = '3-4'
AND class.emp_id = employee.emp_id
)
;
see this sqlfiddle (MySQL)

How to select info from row above?

I want to add a column to my table that is like the following:
This is just an example of how the table is structured, the real table is more than 10.000 rows.
No_ Name Account_Type Subgroup (New_Column)
100 Sales 3
200 Underwear 0 250 *100
300 Bikes 0 250 *100
400 Profit 3
500 Cash 0 450 *400
So for every time there is a value in 'Subgroup' I want the (New_Column) to get the value [No_] from the row above
No_ Name Account_Type Subgroup (New_Column)
100 Sales 3
150 TotalSales 3
200 Underwear 0 250 *150
300 Bikes 0 250 *150
400 Profit 3
500 Cash 0 450 *400
There are cases where the table is like the above, where two "Headers" are above. And in that case I also want the first above row (150) in this case.
Is this a case for a cursor or what do you recommend?
The data is ordered by No_
--EDIT--
Starting from the first line and then running through the whole table:
Is there a way I can store the value for [No_] where [Subgroup] is ''?
And following that insert this [No_] value in the (New_Column) in each row below having value in the [Subgroup] row.
And when the [Subgroup] row is empty the process will keep going, inserting the next [No_] value in (New_Column), that is if the next line has a value in [Subgroup]
Here is a better image for what I´m trying to do:
SQL Server 2012 suggests using Window Offset Functions.
In this case : LAG
Something like this:
SELECT [No_]
,[Name]
,[Account_Type]
,[Subgroup]
,LAG([No_]) OVER(PARTITION BY [Subgroup]
ORDER BY [No_]) as [PrevValue]
FROM table
Here is an example from MS:
http://technet.microsoft.com/en-us/library/hh231256.aspx
The ROW_NUMBER function will allow you to find out what number the row is, but because it is a windowed function, you will have to use a common table expression (CTE) to join the table with itself.
WITH cte AS
(
SELECT [No_], Name, Account_Type, Subgroup, [Row] = ROW_NUMBER() OVER (ORDER BY [No_])
FROM table
)
SELECT t1.*, t2.[No_]
FROM cte t1
LEFT JOIN cte t2 ON t1.Row = t2.Row - 1
Hope this helps.
Next query will return Name of the parent row instead of the row itself, i.e. Sales for both Sales, Underwear, Bikes; and Profit for Profit, Cash:
select ISNULL(t2.Name, t1.Name)
from table t1
left join table t2 on t1.NewColumn = t2.No
So in SQL Server 2008 i created test table with 3 values in it:
create table #ttable
(
id int primary key identity,
number int,
number_prev int
)
Go
Insert Into #ttable (number)
Output inserted.id
Values (10), (20), (30);
Insert in table, that does what you need (at least if understood correctly) looks like this:
declare #new_value int;
set #new_value = 13; -- NEW value
Insert Into #ttable (number, number_prev)
Values (#new_value,
(Select Max(number) From #ttable t Where t.number < #new_value))
[This part added] And to work with subgroup- just modify the inner select to filter out it:
Select Max(number) From #ttable t
Where t.number < #new_value And Subgroup != #Subgroup
SELECT
No_
, Name
, Account_Type
, Subgroup
, ( SELECT MAX(above.No_)
FROM TableX AS above
WHERE above.No_ < a.No_
AND above.Account_Type = 3
AND a.Account_Type <> 3
) AS NewColumn
FROM
TableX AS a