How to UPDATE #temptable - sql

CREATE TABLE #TempProducts (
Id uniqueidentifier,
ManufacturerId uniqueidentifier,
Number varchar(50),
PresentId uniqueidentifier null)
How to UPDATE PresentId field? I have different errors in this:
1) There is already an object named '#TempProducts' in the database.
UPDATE #TempProducts
SET #TempProducts.PresentId = p.Id
FROM #TempProducts JOIN Products p ON (#TempProducts.ManufacturerId = p.ManufacturerId AND #TempProducts.Number = p.Number)
WHERE #TempProducts.Id <> p.Id
2) The multi-part identifier "t.PresentId" could not be bound.
UPDATE #TempProducts
SET t.PresentId = p.Id
FROM #TempProducts t JOIN Products p ON (t.ManufacturerId = p.ManufacturerId AND t.Number = p.Number)
WHERE t.Id <> p.Id

For the Second Error please try:
UPDATE t
SET t.PresentId = p.Id
FROM #TempProducts t JOIN Products p ON (t.ManufacturerId = p.ManufacturerId AND t.Number = p.Number)
WHERE t.Id <> p.Id

UPDATE t
SET t.PresentId = p.Id
FROM #TempProducts t JOIN Products p ON (t.ManufacturerId = p.ManufacturerId AND t.Number = p.Number)
WHERE t.Id <> p.Id
This would be fix for a second error (UPDATE t instead of UPDATE #TempProducts). However, there is no way first query could produce mentioned error.
I am guessing you are executing your CREATE TABLE query again which is producing error because temp table already exists.
You should use a check like this when creating temp tables:
IF (OBJECT_ID('tempdb..#TempProducts') IS NOT NULL) DROP TABLE #TempProducts
CREATE TABLE #TempProducts (
Id uniqueidentifier,
ManufacturerId uniqueidentifier,
Number varchar(50),
PresentId uniqueidentifier null)

For problem 1:(Before the CREATE TABLE syntax )
if object_id(tempdb..#TempProducts) is not null
begin
drop table #TempProducts
end
And for problem 2 i think #techdo is correct.
UPDATE t
SET t.PresentId = p.Id
FROM #TempProducts t JOIN Products p
ON (t.ManufacturerId = p.ManufacturerId AND t.Number = p.Number)
WHERE t.Id <> p.Id

Can't comment due to rep restrictions, but the
IF (OBJECT_ID('tempdb..#TempProducts') IS NOT NULL) DROP TABLE #TempProducts" is no longer needed in SQL Server 2012 or higher. You can now use the simpler DROP TABLE IF EXISTS #TempProducts syntax.

Related

Conversion failed while using ids "where ID in (...)", nvarchar to int

I have a query in MSSQL 2008 like:
IF OBJECT_Id('tempdb..#AccessibleFacilities') IS NOT NULL DROP TABLE #AccessibleFacilities
SELECT u.Userid
, AccesibleFacilityIds = dbo.GetCommaDelimitedString(upf.Facility_Id)
INTO #AccessibleFacilities
FROM Users u
INNER join UserProfileFacilities upf on upf.UserProfile_Id = up.Id
WHERE LOWER(u.Userid) = LOWER(#userId)
GROUP BY u.Userid
This query returns AccessibleFacilityIds like ",1,2,3,4,5,6,". Please note that I am not able to modify GetCommaDelimitedString function.
What I actually need to do is that using those facility ids to reach provs like below:
INSERT INTO #AccessibleProvs
SELECT Userid = #userId
, AccessibleProvIds = dbo.GetCommaDelimitedString(distinct p.Id)
FROM Provs p
inner join ProvFacs pf on p.Id = pf.Provider_Id
WHERE pf.Facility_Id in
(select a.AccesibleFacilityIds from #AccessibleFacilities a)
However, it gives me an error like:
Conversion failed when converting the nvarchar value ',1,2,3,4,5,6,'
to data type int.
I tried removing the comma signs at the start and end like below to fix it, but it did not help:
...
where pf.Facility_Id in (
select SUBSTRING(a.AccesibleFacilityIds,2,LEN(a.AccesibleFacilityIds)-2)
from #AccessibleFacilities a
)
Any advice would be appreciated. Thanks.
Instead of converting Facility_Id into a comma delimited string, why not keep it as a usable column in your temp table?
if object_Id('tempdb..#AccessibleFacilities') is not null drop table #AccessibleFacilities;
select
u.UserId
, upf.Facility_Id
into #AccessibleFacilities
from Users u
inner join UserProfileFacilities upf
on upf.UserProfile_Id = up.Id
Then use it as you did with in() or with exists():
insert into #AccessibleProvs
select
UserId = #userId
, AccessibleProvIds = dbo.GetCommaDelimitedString(distinct p.Id)
from Provs p
inner join ProvFacs pf
on p.Id = pf.Provider_Id
where exists (
select 1
from #AccessibleFacilities a
where a.Facility_Id = pf.Facility_Id
--and a.UserId = #UserId -- Do you need to check Facility_Id by User?
)
If you have the value for #UserId in the beginning, you could limit your temp table usage to just the user you need. Hopefully this code is not meant for use in some sort of cursor or other loop.

How can I perform the Count function with a where clause?

I have my database setup to allow a user to "Like" or "Dislike" a post. If it is liked, the column isliked = true, false otherwise (null if nothing.)
The problem is, I am trying to create a view that shows all Posts, and also shows a column with how many 'likes' and 'dislikes' each post has. Here is my SQL; I'm not sure where to go from here. It's been a while since I've worked with SQL and everything I've tried so far has not given me what I want.
Perhaps my DB isn't setup properly for this. Here is the SQL:
Select trippin.AccountData.username, trippin.PostData.posttext,
trippin.CategoryData.categoryname, Count(trippin.LikesDislikesData.liked)
as TimesLiked from trippin.PostData
inner join trippin.AccountData on trippin.PostData.accountid = trippin.AccountData.id
inner join trippin.CategoryData on trippin.CategoryData.id = trippin.PostData.categoryid
full outer join trippin.LikesDislikesData on trippin.LikesDislikesData.postid =
trippin.PostData.id
full outer join trippin.LikesDislikesData likes2 on trippin.LikesDislikesData.accountid =
trippin.AccountData.id
Group By (trippin.AccountData.username), (trippin.PostData.posttext), (trippin.categorydata.categoryname);
Here's my table setup (I've only included relevant columns):
LikesDislikesData
isliked(bit) || accountid(string) || postid(string
PostData
id(string) || posttext || accountid(string)
AccountData
id(string) || username(string)
CategoryData
categoryname(string)
Problem 1: FULL OUTER JOIN versus LEFT OUTER JOIN. Full outer joins are seldom what you want, it means you want all data specified on the "left" and all data specified on the "right", that are matched and unmatched. What you want is all the PostData on the "left" and any matching Likes data on the "right". If some right hand side rows don't match something on the left, then you don't care about it. Almost always work from left to right and join results that are relevant.
Problem 2: table alias. Where ever you alias a table name - such as Likes2 - then every instance of that table within the query needs to use that alias. Straight after you declare the alias Likes2, your join condition refers back to trippin.LikesDislikesData, which is the first instance of the table. Given the second one in joining on a different field I suspect that the postid and accountid are being matched on the same row, therefore it should be AND together, not a separate table instance. EDIT reading your schema closer, it seems this wouldn't be needed at all.
Problem 3: to solve you Counts problem separate them using CASE statements. Count will add the number of non NULL values returned for each CASE. If the likes.liked = 1, then return 1 otherwise return NULL. The NULL will be returned if the columns contains a 0 or a NULL.
SELECT trippin.PostData.Id, trippin.AccountData.username, trippin.PostData.posttext,
trippin.CategoryData.categoryname,
SUM(CASE WHEN likes.liked = 1 THEN 1 ELSE 0 END) as TimesLiked,
SUM(CASE WHEN likes.liked = 0 THEN 1 ELSE 0 END) as TimesDisLiked
FROM trippin.PostData
INNER JOIN trippin.AccountData ON trippin.PostData.accountid = trippin.AccountData.id
INNER JOIN trippin.CategoryData ON trippin.CategoryData.id = trippin.PostData.categoryid
LEFT OUTER JOIN trippin.LikesDislikesData likes ON likes.postid = trippin.PostData.id
-- remove AND likes.accountid = trippin.AccountData.id
GROUP BY trippin.PostData.Id, (trippin.AccountData.username), (trippin.PostData.posttext), (trippin.categorydata.categoryname);
Then "hide" the PostId column in the User Interface.
Instead of selecting Count(trippin.LikesDislikesData.liked) you could put in a select statement:
Select AccountData.username, PostData.posttext, CategoryData.categoryname,
(select Count(*)
from LikesDislikesData as likes2
where likes2.postid = postdata.id
and likes2.liked = 'like' ) as TimesLiked
from PostData
inner join AccountData on PostData.accountid = AccountData.id
inner join CategoryData on CategoryData.id = PostData.categoryid
USE AdventureWorksDW2008R2
GO
SET NOCOUNT ON
GO
/*
Default
*/
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO
BEGIN TRAN
IF OBJECT_ID('tempdb.dbo.#LikesDislikesData') IS NOT NULL
BEGIN
DROP TABLE #LikesDislikesData
END
CREATE TABLE #LikesDislikesData(
isLiked bit
,accountid VARCHAR(50)
,postid VARCHAR(50)
);
IF OBJECT_ID('tempdb.dbo.#PostData') IS NOT NULL
BEGIN
DROP TABLE #PostData
END
CREATE TABLE #PostData(
postid INT IDENTITY(1,1) NOT NULL
,accountid VARCHAR(50)
,posttext VARCHAR(50)
);
IF OBJECT_ID('tempdb.dbo.#AccountData') IS NOT NULL
BEGIN
DROP TABLE #AccountData
END
CREATE TABLE #AccountData(
accountid INT
,username VARCHAR(50)
);
IF OBJECT_ID('tempdb.dbo.#CategoryData') IS NOT NULL
BEGIN
DROP TABLE #CategoryData
END
CREATE TABLE #CategoryData(
categoryname VARCHAR(50)
);
INSERT INTO #AccountData VALUES ('1', 'user1')
INSERT INTO #PostData VALUES('1','this is a post')
INSERT INTO #LikesDislikesData (isLiked ,accountid, postid)
SELECT '1', P.accountid, P.postid
FROM #PostData P
WHERE P.posttext = 'this is a post'
SELECT *
FROM #PostData
SELECT *
FROM #LikesDislikesData
SELECT *
FROM #AccountData
SELECT COUNT(L.isLiked) 'Likes'
,P.posttext
,A.username
FROM #PostData P
JOIN #LikesDislikesData L
ON P.accountid = L.accountid
AND L.IsLiked = 1
JOIN #AccountData A
ON P.accountid = A.accountid
GROUP BY P.posttext, A.username
SELECT X.likes, Y.dislikes
FROM (
(SELECT COUNT(isliked)as 'likes', accountid
FROM #LikesDislikesData
WHERE isLiked = 1
GROUP BY accountid
) X
JOIN
(SELECT COUNT(isliked)as 'dislikes', accountid
FROM #LikesDislikesData
WHERE isLiked = 0
GROUP BY accountid) Y
ON x.accountid = y.accountid)
IF (XACT_STATE() = 1 AND ERROR_STATE() = 0)
BEGIN
COMMIT TRAN
END
ELSE IF (##TRANCOUNT > 0)
BEGIN
ROLLBACK TRAN
END
How do you think about the solution? We create a new table SummaryReport(PostID,AccountID,NumberOfLikedTime,NumberOfDislikedTimes).
An user clicks on LIKE or DISLIKE button we update the table. After that, you can query as you desire. Another advantage, the table can be served reporting purpose.

How to delete with these conditions?

How can I delete rows which meet several conditions from a table without primary key? (actually the primary key is formed by every column)
After so many tries I have a code that first creates a temporary table where it inserts the rows I want to delete and finally I try to delete the rows from original table which meet the conditions comparing to temporary table.
But it gives me the error about cannot linking the several parts identifier #temp.idCarga
Maybe it's easy but I have been trying so much time and I cannot focus properly.
CREATE TABLE #TEMP
(
CC int,
idCarga int,
Tipo nvarchar(50),
Importe float,
Bloque nvarchar(50),
idsistema int
)
INSERT INTO #TEMP(CC,idCarga,Importe,Bloque,Tipo,IdSistema)
select distinct CI.CC,CI.idCarga,CI.Importe,CI.Bloque,CI.Tipo,CI.idSistema
from CONT_INGRESOS_InformeMayor CI
INNER JOIN
(
SELECT idCarga,CC,Bloque,Importe,TIpo
FROM CONT_INGRESOS_InformeMayor
) CI2
ON CI.CC = CI2.CC
AND CI.Bloque = CI2.Bloque
AND CI.TIpo <> CI2.Tipo
WHERE CI.idCarga = #idCarga
AND CI2.idCarga = #idCarga
AND CI.Importe = 0
DELETE
FROM CONT_INGRESOS_InformeMayor
WHERE idCarga = #temp.idCarga
AND tipo = #temp.tipo
AND importe = #temp.importe
and bloque = #temp.bloque
You missed a join on your DELETE. Try this:
DELETE _d
FROM CONT_INGRESOS_InformeMayor AS _d
INNER JOIN #temp AS _t
ON _d.idCarga = _t.idCarga
AND _d.tipo = _t.tipo
AND _d.importe = _t.importe
AND _d.bloque = _t.bloque
Your DELETE is missing a JOIN to your #temp table
DELETE t1
FROM CONT_INGRESOS_InformeMayor t1
INNER JOIN #temp t
ON t1.idCarga = t.idCarga
AND t1.tipo = t.tipo
AND t1.importe = t.importe
and t1.bloque = t.bloque
On the other hand, you could try deleting the rows without involving a temporary table:
DELETE FROM CI
from CONT_INGRESOS_InformeMayor CI
INNER JOIN
(
SELECT idCarga,CC,Bloque,Importe,TIpo
FROM CONT_INGRESOS_InformeMayor
) CI2
ON CI.CC = CI2.CC
AND CI.Bloque = CI2.Bloque
AND CI.TIpo <> CI2.Tipo
WHERE CI.idCarga = #idCarga
AND CI2.idCarga = #idCarga
AND CI.Importe = 0

Error using Update Join statement from a Table Variable

If I make a table variable here:
declare #Table Table (ProductID int, Color = varchar(60))
Then populate it of course, and try to use it in an Update with Join statement like below, I get errors.
UPDATE [Product]
SET [Product].[Active] = 1
,[Product].[Color] = t.[Color]
INNER JOIN #Table t
ON t.[ProductID] = [Product].[ProductID]
Error:
Msg 156, Level 15, State 1, Procedure
Incorrect syntax near the keyword 'INNER'.
Any suggestions how to do this?
You can also do this (works on SQL Server and all ANSI SQL conforming database):
UPDATE [Product] SET
[Product].[Active] = 1
,[Product].[Color] = t.[Color]
FROM #Table t
WHERE t.[ProductID] = [Product].[ProductID]
There's something to be desired from SQL Server's proprietary UPDATE FROM though, you can easily change the UPDATE statement to make it match whole table regardless if there's no matching rows.
It's easy to fashion this matched-rows-only update... http://www.sqlfiddle.com/#!3/8b5a3/26
update p SET
Qty = t.Qty
from Product p
inner join Latest t
on t.ProductId = p.ProductId;
...to an UPDATE that matches all rows, you merely change the INNER JOIN to LEFT JOIN: http://www.sqlfiddle.com/#!3/8b5a3/27
update p SET
Qty = ISNULL(t.Qty,0)
from Product p
left join Latest t
on t.ProductId = p.ProductId;
select * from Product;
Whereas if you want to fashion the ANSI SQL UPDATE with matched-rows-only ... http://www.sqlfiddle.com/#!3/8b5a3/28
update Product SET
Qty = t.Qty
from Latest t
where t.ProductId = Product.ProductId
...to UPDATE statement that matches all rows, you have to adjust your query a bit: http://www.sqlfiddle.com/#!3/8b5a3/29
update Product SET
Qty = ISNULL(t.Qty, 0)
from
(
select x.ProductId, lat.Qty
from Product x
left join Latest lat on lat.ProductId = x.ProductId
) as t
where t.ProductId = Product.ProductId;
Though as most choices in development, one should weigh the pros and cons in terms of code readability/maintainability against flexibility
Data sample:
create table Product
(
ProductId int primary key not null,
Name varchar(50) not null,
Qty int not null
);
insert into Product(Name,Qty) values
(1,'CAR',1),
(2,'Computer',1000),
(3,'Shoes',2);
create table Latest
(
ProductId int primary key not null,
Qty int not null
);
insert into Latest(ProductId, Qty) values
(2,2000),
(3,3);

Output Clause: The multi-part identifier could not be bound

I am running in to the dreaded "The multi-part identifier could not be bound" error on a stored procedure I am currently working on. I have a few questions in regards to the query below.
Why am I getting this error?
Why would this error occur on ImportFundingDateTime instead of FloorplanId given that they both come from the same query, but FloorplanId is listed first in the output clause?
Can I adjust this query to not get the error while still keeping the general structure the same?
.
DECLARE #Results Table(
[FloorPlanId] UNIQUEIDENTIFIER,
[ImportFundingDateTime] DATETIME,
[TimeStamp] VARBINARY(8),
[BusinessId] UNIQUEIDENTIFIER
)
UPDATE CacRecord
SET MatchFound = 1
OUTPUT fp.[FloorplanId], cr.[ImportFundingDateTime],
fp.[TimeStamp], buyer.[BusinessId]
INTO #Results( [FloorplanId], [ImportFundingDateTime],
[TimeStamp], [BusinessId])
FROM CacRecord cr WITH (NOLOCK)
INNER JOIN CacBatch cb WITH (NOLOCK)
ON cr.CacBatchId = cb.CacBatchId
INNER JOIN Floorplan fp WITH (NOLOCK)
ON fp.UnitVIN = cr.ImportVin
AND COALESCE(fp.UnitVIN, '') <> ''
INNER JOIN Business buyer WITH (NOLOCK)
ON buyer.BusinessId = fp.BuyerBusinessId
LEFT OUTER JOIN BusinessContact bc WITH (NOLOCK)
ON bc.BusinessId = buyer.BusinessId
LEFT OUTER JOIN Contact c WITH (NOLOCK)
ON c.ContactId = bc.ContactId
WHERE cb.CacJobInstanceId = #cacJobInstanceId
AND fp.FloorplanStatusId = 1 --Approved
AND COALESCE(cr.ImportVin, '') <> ''
AND 1 =
CASE
WHEN cr.ImportFein = buyer.FederalTaxID
AND COALESCE(cr.ImportFein, '') <> '' THEN 1
WHEN cr.ImportSsn = c.Ssn
AND COALESCE(cr.ImportSsn, '') <> '' THEN 1
ELSE 0
END;
Please recheck the syntax of the OUTPUT clause OUTPUT on MSDN
Syntax
<column_name> ::=
{ DELETED | INSERTED | from_table_name } . { * | column_name }
from_table_name
Is a column prefix that specifies a table included in the FROM clause
of a DELETE or UPDATE statement that is used tospecify the rows to
update or delete.
It looks like you have aliased CacRecord in the FROM clause as "cr", but have not correlated that with the UPDATE clause.
Note: Even with it aliases in the FROM clause and NOT aliased in the UPDATE cause, SQL Server appears to recognize CacRecord as the UPDATE table, requiring you to use INSERTED instead of cr as the virtual table name.
UPDATE cr
SET MatchFound = 1
OUTPUT fp.[FloorplanId], INSERTED.[ImportFundingDateTime],
fp.[TimeStamp], buyer.[BusinessId]
INTO #Results( [FloorplanId], [ImportFundingDateTime],
[TimeStamp], [BusinessId])
FROM CacRecord cr WITH (NOLOCK)
INNER JOIN CacBatch cb WITH (NOLOCK)
ON cr.CacBatchId = cb.CacBatchId
INNER JOIN Floorplan fp WITH (NOLOCK)
ON fp.UnitVIN = cr.ImportVin
AND COALESCE(fp.UnitVIN, '') <> ''
INNER JOIN Business buyer WITH (NOLOCK)
ON buyer.BusinessId = fp.BuyerBusinessId
LEFT OUTER JOIN BusinessContact bc WITH (NOLOCK)
ON bc.BusinessId = buyer.BusinessId
LEFT OUTER JOIN Contact c WITH (NOLOCK)
ON c.ContactId = bc.ContactId
WHERE cb.CacJobInstanceId = #cacJobInstanceId
AND fp.FloorplanStatusId = 1 --Approved
AND COALESCE(cr.ImportVin, '') <> ''
AND 1 =
CASE
WHEN cr.ImportFein = buyer.FederalTaxID
AND COALESCE(cr.ImportFein, '') <> '' THEN 1
WHEN cr.ImportSsn = c.Ssn
AND COALESCE(cr.ImportSsn, '') <> '' THEN 1
ELSE 0
END;
For visitors to this question, this code block shows multiple tables being referenced in the OUTPUT clause correctly.
create table TO1 (id int, a int);
create table TO2 (id int, b int);
create table TO3 (id int, c int);
insert into TO1 select 1,1;
insert into TO2 select 1,2;
insert into TO3 select 1,3;
insert into TO3 select 1,4;
declare #catch table (a int, b int, c int)
update c
set c = a.a
output a.a, b.b, INSERTED.c
into #catch(a,b,c)
from TO1 a
inner join TO2 b on a.id=b.id
inner join TO3 c on a.id=c.id