How to join table variables? [duplicate] - sql

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
T-SQL: How to join #variable tables (another try)
First: I'm using SQL Server 2008.
In a complex algorithm that involves a lot of data, I have been using a technical of creating intermediate table variables:
DECLARE #table AS TABLE (Col1 INT, Col2 VARCHAR(100))
Unfortunately, SQL Server does not support JOIN'ing #variable tables, it is only allowed to join "true" tables, those in the database.
I could do the "manual" join, like
FROM #table1 t1, #table2 t2
WHERE t1.Id = t2.Id
This results in a INNER JOIN, but this is wrong for me. The question is: How do FULL JOIN two #variable tables?

What do you mean by SQL doesn't support Joining table variables?
It works for me
DECLARE #table1 AS TABLE (Col1 INT, Col2 VARCHAR(100))
DECLARE #table2 AS TABLE (Col1 INT, Col2 VARCHAR(100))
SELECT *
FROM #table1 t1
FULL JOIN #table2 t2 on t1.Col1 = t2.Col1

You should be able to do a join using an #tableVariable
SELECT *
FROM table1 t
FULL JOIN #tableVariable tv
ON (tv.col = cnc.col)
Could it have anything to do with your compatability setting? (mine is at 100)
sp_dbcmptlevel 'database_name'
ALTER DATABASE database_name
SET COMPATIBILITY_LEVEL = { 80 | 90 | 100 }

I'm not sure what you're asking, as joining works just fine for table variables. See this example:
declare #table as table (Col1 int, Col2 varchar(100))
declare #table2 as table (Col1 int, Col2 varchar(100))
insert into #table
select 1, 'A'
union all
select 1, 'C'
union all
select 1, 'D'
insert into #table2
select 2, 'A'
union all
select 2, 'B'
union all
select 2, 'D'
union all
select 2, 'E'
select
*
from
#table t1 full outer join
#table2 t2 on t1.Col2 = t2.Col2
select
*
from
#table t1 left join
#table2 t2 on t1.Col2 = t2.Col2
select
*
from
#table t1 right join
#table2 t2 on t1.Col2 = t2.Col2
select
*
from
#table t1 join
#table2 t2 on t1.Col2 = t2.Col2

Related

Update statement with Where Not Exists

I am trying to do the following:
Set the status column to 1 when the row in the first table (variable) does not exist in the second one.
I tried this:
update #table1
set status=1
where NOT EXISTS (select top 1 1 from #table2 where #table1.foo=#table2.foo)
But this doesn't even compile, not recognizing #table1 in the Where statement.
Must declare the scalar variable "#table1".
Any clue about this?
Your approach is fine. You just need table aliases because the # is used to in SQL Server to represent variables (scalars or tables) and is hence problematic for aliases:
update t1
set status = 1
from #table1 t1
where not exists (select 1 from #table2 t2 where t2.foo = t1.foo);
Note that the top 1 is unnecessary in the subquery.
You can do this kind of thing by joining the two tables with a LEFT JOIN and checking the right side for NULL:
UPDATE t1
SET t1.status=1
FROM #table1 t1
LEFT JOIN #table2 t2
ON t1.foo = t2.foo
WHERE t2.foo IS NULL
The specific error you got is because you haven't got a statement declaring #table1 as a table variable, like DECLARE #table1 TABLE (foo int) for example. If table1 is not a variable, you don't need the #.
no need any top inside scaler query
update #table1
set status=1
where NOT EXISTS (select 1 from #table2 where #table1.foo=#table2.foo)
cause exists return boolean
you could use below query
update #table1
set status=1
where #table1.foo not in ( select foo from #table2 where foo is not null)
There are multiple ways - inner query with NOT IN and NOT EXISTS and JOIN query:
update tab1 set status = 1 where name not in (select name from tab2);
update tab1 set status = 1 where not exists (select 1 from tab2 where tab1.name=tab2.name);
update tab1 set status = 1 from tab1 left outer join tab2 on tab1.name = tab2.name where tab2.name is null;
Sample schema to run above queries;
create table tab1(name varchar(30), status int);
create table tab2(name varchar(30));
insert into tab1 values('a', 5);
insert into tab1 values('b', 6);
insert into tab1 values('c', 7);
insert into tab1 values('d', 8);
insert into tab2 values('a');
insert into tab2 values('d');
You have to declare table1 and table2 variables
DECLARE #table1 YOUR_TABLE1_NAME;
DECLARE #table2 YOUR_TABLE2_NAME;
update #table1
set status=1
where NOT EXISTS (select top 1 from #table2 where #table1.foo=#table2.foo)
You should use alias name for both table.
DECLARE #TABLE_1 TABLE (DEPT_NAME VARCHAR(50),DEP_ID INT)
INSERT INTO #TABLE_1(DEPT_NAME,DEP_ID)
SELECT 'IT',1 UNION ALL
SELECT 'HR',2 UNION ALL
SELECT 'ACCOUNT',3 UNION ALL
SELECT 'ADMIN',4 UNION ALL
SELECT 'SALES',5 UNION ALL
SELECT 'CEO',7
DECLARE #TABLE_2 TABLE (E_ID INT,EMP_NAME VARCHAR(50),DEP_ID INT)
INSERT INTO #TABLE_2(E_ID,EMP_NAME,DEP_ID)
SELECT 1,'JHON',1 UNION ALL
SELECT 2,'LITA',2 UNION ALL
SELECT 3,'MATT',1 UNION ALL
SELECT 4,'JEFF',1 UNION ALL
SELECT 5,'BROCK',2 UNION ALL
SELECT 6,'BOB',5 UNION ALL
SELECT 7,'SAM',4 UNION ALL
SELECT 8,'DAVID',3 UNION ALL
SELECT 9,'JACK',1 UNION ALL
SELECT 10,'GARY',4 UNION ALL
SELECT 11,'DONALD',6
SELECT * FROM #TABLE_1 A WHERE NOT EXISTS (SELECT DEP_ID FROM #TABLE_2 B WHERE A.DEP_ID=B.DEP_ID )

Put a table of values as an argument to a query

I need to do something like this:
SET #MyTableAsArgument = 'Foo;Bar\n1;2\n3;4\n'; -- CSV or any other table-format
SET #AnOtherArgument = 'somedata';
SELECT * FROM table1 t1, #MyTableAsArgument t2
WHERE t1.foo = t2.foo
AND t1.bar = #AnOtherArgument
Is there a way to do this?
The only other solution I see is:
Create a temporary table tmp1
Insert my MyTableAsArgument to the tmp1
Do My query on table1 and tmp1
Delete my temporary table tmp1
I am not sure if this is an abuse of temporary tables.
Is there a significant performance overhead with temporary tables as they are used for queries?
Can you use a table variable or temporary table?
DECLARE #MyTable TABLE (foo VARCHAR(255));
INSERT INTO #MyTable (foo)
VALUES ('Foo'), ('Bar\n12\n3'), ('4\n');
SET #AnOtherArgument = 'somedata';
SELECT t1.*
FROM table1 t1
WHERE t1.foo IN (SELECT foo FROM #MyTable) AND
t1.bar = #AnOtherArgument;
If this is not possible, you can use a SPLIT() functions -- STRING_SPLIT() is built into the most recent versions -- but other versions are on the web:
SELECT *
FROM table1 t1
WHERE t1.foo IN (SELECT foo FROM string_split(#MyTableLIST, ';') ss(foo)) AND
t1.bar = #AnOtherArgument;
#Cosinus, there is a temp table variable too in SQL. This allows you to define the columns you want in that table and using a 'union all' you can insert elements in that table.
See this mockup below.
DECLARE #MyTableAsArgument table(Name varchar(20), foo varchar(50), descb varchar(100), pj_id int)
DECLARE #AnOtherArgument varchar(20) = 'somedata';
INSERT into #MyTableAsArgument
SELECT 'James', 'iphone', 'cell phone', 1 union all
SELECT 'Michael', 'macbook', 'laptop', 2 union all
SELECT 'Henry', 'windows', 'os', 3
SELECT *
FROM
table1 t1
Join #MyTableAsArgument t2 ON
t1.foo = t2.foo
AND
t1.bar = #AnOtherArgument

Match the codes and copy columns

I am working in SQL Server 2008. I have 2 tables Table1 & Table2.
Table1 has columns
SchoolCode, District, Type, SchoolName
and Table2 has columns
SchoolCode1, District1, Type1, SchoolName1
SchoolCode columns in both tables have the same codes like "1234"; code is the same in both schoolcode columns.
Now I want to copy the District, Type and SchoolName column values from Table1 to Table2 if SchoolCode in both tables is same.
I think the query will use join but I don't know how it works. Any help on how I can do this task?
Maybe use an update statement in join if by copying over you mean updating rows
update t2
set
District1= District,
Type1= Type,
SchoolName1= SchoolName
from Table1 t1
join
Table2 t2
on t1.SchoolCode=t2.SchoolCode1
I could give you a little bit of idea. here is it:
Insert into table2 (District1, Type1, SchoolName1)
SELECT District, Type, SchoolName
FROM table1
where table1.Schoolcode=table2.Schoolcode1
You have to use Inner join to update data from table 1 to table 2, Inner join will join values that are equal. . To learn more about joins, I highly recommend you to read the below article
SQLServer Joins Explained - W3Schools
Please refer the below code, for the convenience I have used the temporary tables..
DECLARE #Table1 TABLE
(
SchoolCode INT,
District VARCHAR(MAX),
Type VARCHAR(MAX),
SchoolName VARCHAR(MAX)
)
DECLARE #Table2 TABLE
(
SchoolCode1 INT,
District1 VARCHAR(MAX),
Type1 VARCHAR(MAX),
SchoolName1 VARCHAR(MAX)
)
INSERT INTO #Table1
( SchoolCode ,District , Type , SchoolName
)
VALUES ( 1 ,'DIS1' ,'X' ,'A'),
( 2 ,'DIS2' ,'Y' ,'B'),
( 3 ,'DIS3' ,'Z' ,'C'),
( 4 ,'DIS4' ,'D' ,'D'),
( 5 ,'DIS5' ,'K' ,'E')
INSERT INTO #Table2
( SchoolCode1 ,District1 , Type1 , SchoolName1
)
VALUES ( 1 ,'DIS1' ,'X' ,'A'),
( 2 ,NULL ,'Z' ,NULL),
( 3 ,'DIS3' ,'Z' ,'C'),
( 4 ,NULL ,'Z' ,'S'),
( 5 ,'DIS5' ,'K' ,'E')
--BEFORE
SELECT * FROM #Table1
SELECT * FROM #Table2
--Logic UPDATE Table 2
UPDATE t2 SET t2.District1 = t1.District,
t2.Type1 = t1.Type,
t2.SchoolName1 = t1.SchoolName
FROM #Table1 t1
INNER JOIN #Table2 t2 ON t1.SchoolCode = t2.SchoolCode1
-- End Logic UPDATE Table 2
--AFTER
SELECT * FROM #Table1
SELECT * FROM #Table2
You can join tables in an UPDATE statement.
Note, I have aliased the tables, table1 and table2 as t1 and t2 respectively.
This is what I did:
create table Table1
(SchoolCode varchar(50),
District varchar(50),[Type] varchar(50),SchoolName varchar(50))
go
create table Table2
(SchoolCode1 varchar(50), District1 varchar(50),[Type1] varchar(50),SchoolName1 varchar(50))
go
insert into table1 values ('1234','District1','High','Cool School')
insert into table1 values ('2222','District2','Lower','Leafy School')
insert into table2 (SchoolCode1) values ('1234')
go
update t2
set District1 = District,
Type1 = [Type],
SchoolName1 = SchoolName
from table1 t1
join table2 t2
on t2.SchoolCode1 = t1.SchoolCode
go
select * from table2
go

TSQL - The multi-part identifier bounding error

CREATE FUNCTION [dbo].[Test] (#ID INT, #VAL INT)
RETURNS #Return TABLE (ID INT, VAL INT)
AS
BEGIN
INSERT INTO #Return
SELECT #ID, #VAL
RETURN;
END
GO
DECLARE #T1 TABLE (ID INT IDENTITY(1,1), VAL INT)
DECLARE #T2 TABLE (ID INT, VAL INT)
INSERT INTO #T1
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
INSERT INTO #T2
SELECT 1,1
UNION
SELECT 2,4
UNION
SELECT 3,3
SELECT *
FROM #T1 T1
LEFT JOIN #T2 T2 ON T1.[ID] = T2.[ID]
LEFT JOIN [dbo].[Test] (1, COALESCE(T2.[VAL],T1.VAL)) T ON T1.ID = T.ID
GO
DROP FUNCTION [dbo].[Test]
GO
Goal:
To pass in T2.Val into the 2nd param of the fx if available, else pass in T1.Val. Changing the FX definition is not possible.
I can't seem to get this work. I tried ISNULL and that doesn't work either.
If you want to call a table valued function, use APPLY (OUTER APPLY in this case because you are using LEFT JOIN):
SELECT *
FROM #T1 T1 LEFT JOIN
#T2 T2
ON T1.[ID] = T2.[ID] OUTER APPLY
[dbo].[Test](1, COALESCE(T2.[VAL], T1.VAL) ) T;
If you want an additional condition, then use a WHERE clause:
SELECT *
FROM #T1 T1 LEFT JOIN
#T2 T2
ON T1.[ID] = T2.[ID] OUTER APPLY
[dbo].[Test](1, COALESCE(T2.[VAL], T1.VAL) ) T
WHERE t1.ID = T.ID;
That last condition seems strange, though. Why not just pass T1.ID into the function directly?

Merge multiple rows into single value using update Query

Here is the scenario. I have two tables. I want to merge multiple row value to single value using update query.
DECLARE #Table as Table
(
id int,
name varchar(10)
)
insert into #Table values(1,'a')
insert into #Table values(1,'b')
insert into #Table values(1,'c')
select * from #Table
DECLARE #Table2 as Table
(
id int,
name varchar(10)
)
insert into #Table2 values(1,'a')
update t2 set name = t1.name from #Table2 t2
inner join #Table t1 on t1.id=t2.id
select * from #Table2
I want output from #Table2 as by using update query
id name
----- --------
1 a,b,c
;WITH Table1 AS (
SELECT t.id
, STUFF((SELECT ',' + name
FROM #Table
WHERE id = t.id
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,1,'') AS name
FROM #Table t
GROUP BY t.id)
UPDATE t2
SET t2.name = t1.name
FROM #Table2 t2
INNER JOIN Table1 t1 ON t1.id=t2.id