Update statement in SQL Server using two tables - sql-server

This my query
UPDATE #Student_tbl
SET MStudentId = (SELECT StudentId
FROM #StudentHistory_tbl
WHERE UserId NOT IN (SELECT UserId
FROM #Student_tbl)
)
it returns an error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

The error is fairly explicit, when you write:
UPDATE #Student_tbl
SET MStudentId = (
Select StudentId
from #StudentHistory_tbl
where UserId not in (select UserId from #Student_tbl)
)
You are updating all rows in the #Student_tbl. You are trying to set MSStudentId to equal multiple rows, as your select does not return just one row.
You would have to look at either your subquery, to get it to return 1 row, or join the subquery to the 'StudnetHistory_tbl so you are updating the column with a singular row value.

You can use JOINS in update statements. Try something like this:
UPDATE t1
SET t1.MStudentId = t2.Studentid
FROM #Student_tbl AS t1
INNER JOIN #StudentHistory_tbl AS t2 ON t2.UserId = t1.UserId
WHERE t1.MStudentId <> t2.Studentid;

I think you need something like this
UPDATE #Student_tbl
SET MStudentId= a.StudentId
from (Select StudentId,UserId from #StudentHistory_tbl ,#Student_tbl
where #StudentHistory_tbl.UserId <> #Student_tbl.UserId ) a
where a.UserId <> #Student_tbl.UserId
OR
UPDATE #Student_tbl
SET MStudentId= a.StudentId
from (Select StudentId,UserId from #StudentHistory_tbl
where UserId not in (select UserId from #Student_tbl) ) a
where a.UserId not in (select UserId from #Student_tbl)

Related

Postgresql - Update CTE result from CTE Output?

I need to update CTE o/p one of the column value (top 1 record) based on the latest timestamp & then return.
Query
WITH cte AS (
select
dt_zone.zone_name,
dt_material_status.mtstatus_name,
dt_historicalzone.visit_time_in
FROM ((public.dt_historicalzone
INNER JOIN dt_material_status
ON dt_historicalzone.mtstatus_id = dt_material_status.mtstatus_id)
INNER JOIN dt_zone ON dt_historicalzone.zone_id = dt_zone.zone_id)
WHERE material_id = 'ELS46885'
ORDER BY dt_historicalzone.zone_id DESC)
UPDATE cte SET cte.mtstatus_name = true WHERE SELECT * FROM cte LIMIT 1;
SELECT * FROM cte
You may try using an update join, with Postgres' syntax, including a CTE for the limit portion of the query:
WITH cte AS (
SELECT dh.mtstatus_id
FROM dt_historicalzone dh
INNER JOIN dt_zone dz
ON dh.zone_id = dz.zone_id
ORDER BY zone_id DESC
LIMIT 1
)
UPDATE dt_material_status d
SET mtstatus_name = true
FROM cte t
WHERE d.mtstatus_id = t.mtstatus_id AND
d.material_id = 'ELS46885';
when you update a CTE, the background table is getting updated. You can have only one statement below CTE. Post that CTE loses its scope. You can only go for UPDATE statement, post CTE. I have modified the CTE and updated the top 1 row.
The above statement is applicable for SQL Server. In Postgres, the CTE cannot be target of UPDATE statements. See the below error in Postgres.
Query Error: error: relation "cte" cannot be the target of a modifying
statement
WITH cte AS (
select top 1
dt_zone.zone_name,
dt_material_status.mtstatus_name,
dt_historicalzone.visit_time_in
FROM public.dt_historicalzone
INNER JOIN dt_material_status
ON dt_historicalzone.mtstatus_id = dt_material_status.mtstatus_id
INNER JOIN dt_zone ON dt_historicalzone.zone_id = dt_zone.zone_id
WHERE material_id = 'ELS46885'
ORDER BY dt_historicalzone.zone_id DESC)
UPDATE cte
SET mtstatus_name = true
I have tried with sample data for a CTE update. Below works fine in SQL Server.
create table #test(a int)
create table #test2(a int, b int)
insert into #test values (1)
insert into #test2 values (1,1)
;WITH CTE as
(
select top 1 t.a, t2.b
FROM #test as t
join #test2 as t2
on t.a = t2.a
order by t.a desc
)
update cte set b = 0
select * from #test2

Using cte inside current table

I'm trying to create an expression, plase see example below.
with cte1 (ex1)
as
(
select SUM(HasItems)
from InventoryTransTemp where HasItems !=0
)
select distinct TableName,ex1 from InventoryTransTemp where Active=1
I'm getting error Invalid column name 'ex1'.
I want the sum from ex1 to be connected with the current table in select state and also to have where clause,as example active=1
More specific to sum all rows from each TableName which HasItems!=0
You can use a sub-query then.
select distinct
TableName
,ex1 = (select SUM(HasItems) from InventoryTransTemp where HasItems !=0 )
from InventoryTransTemp
where Active=1
If the tables are related, then you need to correlate the sub-query or simply join the tables.
select distinct
t.TableName
,ex1 = (select SUM(t2.HasItems)
from InventoryTransTemp t2
where t2.HasItems !=0
and t1.somecolumn = t2.somecolumn)
from InventoryTransTemp t
where t.Active=1

Insert with Select causes "Subquery returned more than 1 value" eventhough subqueries return expected values

Using MS Sql Server 2008 I'm trying to insert multiple rows into a users_roles table using the fancy Insert/Select syntax. When executing this query, I get the error
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
Both subqueries, when executed on their own, return the expected values. Multiple records in the first subquery and a single record in the second.
insert into users_roles(userid, roleid)
select
(select distinct users.id as userID from users
inner join users_roles on users.id = users_roles.userid
inner join roles on users_roles.roleid = roles.id
where roles.projectid = 1)
,
(select id as roleID from roles where projectid = 1 and name = 'ALL')
What am I missing out here?
SQL does not even know if the second (or first) will return 0, 1, or many
decalare #roleID int;
set #roleID = (select top 1 id from roles where projectid = 1 and name = 'ALL');
insert into users_roles(userid, roleid)
select distinct users.id as userID, #roleID
from users
inner join users_roles on users.id = users_roles.userid
inner join roles on users_roles.roleid = roles.id
where roles.projectid = 1;
You can use this syntax to insert multiple records or a single record, but not at the same time! As it stands, your query is trying to select multiple values in the first column, and a single value in the second.
You don't need two subqueries. Just make your first subquery into the outer query (returning multiple rows), and your second subquery will then return a single row for each:
insert into users_roles(userid, roleid)
select distinct users.id as userID,
(select id as roleID from roles where projectid = 1 and name = 'ALL') as roleID
from users
inner join users_roles on users.id = users_roles.userid
inner join roles on users_roles.roleid = roles.id
where roles.projectid = 1)
Note that you don't really need the column aliases, they're just there for clarity.
It is the multiple rows in the first subquery that is causing the issue. You have it as a column the way you built this. If it returns multiple rows sql doesn't know which row you want.
Something like this is probably what you are looking for.
select distinct users.id as userID from users
inner join users_roles on users.id = users_roles.userid
inner join roles on users_roles.roleid = roles.id
cross apply
(
select id as roleID from roles where projectid = 1 and name = 'ALL'
)
where roles.projectid = 1

MS SQL 2008 - update record with a value if the grouped total meets a condition

I am trying to figure out how to update record with a value only in case that the grouped total of a particular type of transactions type is over zero.
In other words, I group my transactions by payment type. If the grouped payment type total is greater than zero, I would like to update each of the transaction in the group with a value.
I cannot figure out that correct statement. Could anyone help please?
UPDATE
T
SET
T.col1 = OT.col1,
T.col2 = OT.col2
FROM
Some_Table T
INNER JOIN
Other_Table OT ON T.id = OT.id
WHERE
T.col3 = 'xyz'
-- GROUP BY T.col1
-- HAVING SUM(amount) > 0
You can use a CTE together with a SUM() OVER():
;WITH ToUpdate AS (
SELECT T.col1 AS tcol1, OT.col1 AS otcol1, T.col2 AS tcol2, OT.col2 AS otcol2,
SUM(amount) OVER (PARTITION BY T.col1) AS sumAmount
FROM Some_Table T
INNER JOIN Other_Table OT ON T.id = OT.id
)
UPDATE ToUpdate
SET
tcol1 = otcol1,
tcol2 = otcol2
WHERE sumAmount > 0
The above query will update every row of Some_Table that belongs to a col1 partition with SUM(amount) > 0.

T-SQL - Select Using SubQuery

I have a SQL query where I have in my where clause a list into a IN condition.
Example of what I mean:
WHERE Id IN (11111,11112)
And what I try to do is the following: I have a linked server query where I have an IN clause.
And I have a subquery where I use a JOIN table to cross data but I need that in the IN condition use the same Id like the main query.
I hope you guys understand what I try to do:
Here's my code:
SELECT
Name,
Street,
Number,
(SELECT loginUser FROM [LinkedServer].[Database].[dbo].[Users] T1
INNER JOIN [LinkedServer].[Database].[dbo].[General] T2
ON T2.IdUser = T1.Id
WHERE T2.Id IN (11111,11112,11113,11114,11115)
)
FROM [LinkedServer].[Database].[dbo].[General]
WHERE Id IN (11111,11112,11113,11114,11115)
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.
To reuse same set of ids you could use Table Variable.
DECLARE #T TABLE(ID INT);
INSERT INTO T
SELECT 11111 UNION ALL SELECT 11112 ....
then
SELECT * FROM
(SELECT Varchar1,
Varchar2,
Varchar3, loginUser FROM [LinkedServer].[Database].[dbo].[Table] T1
INNER JOIN [LinkedServer].[Database].[dbo].[Table] T2
ON T2.INT1 = T1.INT1
WHERE T2.Id IN (select id from #T)
) AS X WHERE
X.Id IN (select id from #T)
Consider using a join instead of a correlated-subquery:
SELECT General.Name
, General.Street
, General.Number
, Users.loginUser
FROM [LinkedServer].[Database].[dbo].[General]
LEFT
JOIN [LinkedServer].[Database].[dbo].[Users]
ON Users.Id = General.IdUser
WHERE General.Id IN (11111, 11112, 11113, 11114, 11115)
This will return the loginUser where possible.
i have solved it finally.
The Problem was that the subquery havenĀ“t a where condition to extract a specific Id.
Without a WHERE Condition the query return more than 1 value.
What i have done:
Thanks for the advice and his solution Author: "LIUFA".
With a combination of his code and some correction of my code i get the solution.
I have add one more column Id and give it an alias. In the subquery i have done the select from the Temp table
using a where condition. And its Working. Perfect.
Hope that this solution can help somebody to solved a related issue.
Finally Code:
DECLARE #T TABLE(ID INT);
INSERT INTO #T
Select ReferenceId From MyBigData
SELECT,
A.Id,
Name,
Street,
Number,
(SELECT loginUser FROM [LinkedServer].[Database].[dbo].[Users] T1
INNER JOIN [LinkedServer].[Database].[dbo].[General] T2
ON T2.IdUser = T1.Id
WHERE T2.Id IN (SELECT Id FROM #T WHERE Id = A.Id)
)
FROM [LinkedServer].[Database].[dbo].[General]
WHERE Id IN (SELECT Id FROM #T)

Resources