T-SQL: #variable | inner join | 2 database - tsql

SQL Server 2008 R2 - 2 database in the instance, Mandant_2 and tlock.
I need a inner join SQL command between the databases with #variable:
DECLARE #t AS TABLE (
c VARCHAR(100)
)
INSERT #t VALUES ('[Mandant_2].[dbo].[tartikel]')
UPDATE tlock.dbo.temp SET Warengruppe = a.kWarengruppe
FROM tlock.dbo.temp d
INNER JOIN #t a ON d.HAN = a.cHAN
I get an error:
Message 207, Level 16, State 1, Procedure spMyStoreProduced, line 39
Invalid column name 'cHAN'.
Unfortunately I have no idea why.
Thanks

What does mean last line in your code
INNER JOIN #t a ON d.HAN = a.cHAN
Table #t has column named c, but there is no column named cHAN.
Did you mean to say
INNER JOIN #t a ON d.HAN = a.c
Proof of concept:
just try this
DECLARE #t AS TABLE (
c VARCHAR(100)
)
INSERT #t VALUES ('[Mandant_2].[dbo].[tartikel]')
select cHAN from #T
and you will get
Msg 207, Level 16, State 1, Line 7
Invalid column name 'cHAN'.

Related

Use table column value as calculation for result in another column

I have a table with a column named "Calc" varchar(50). This column contains math calculations such as 1+1, 9*9, 10/2, 10-2 etc.
Is there way in an update query to apply this calculation from the column and output the result in the same table in the "Results" column varchar(50).
As you know by now, SQL Server does not have an EVAL() function, nor does it support macro substitution.
However, this can be done via dynamic SQL
Example
Create table #YourTable (id int,[Calc] varchar(150),Results varchar(150))
Insert Into #YourTable Values
(1,'1+1',null)
,(2,'9*9',null)
,(3,'10/2',null)
,(4,'10-2',null)
,(5,'datediff(DAY,''2018-01-01'',getdate())',null) -- Added Just for Fun
Declare #SQL varchar(max) = Stuff((Select ',' + concat('(',ID,',',[Calc],')')
From #YourTable A
For XML Path (''))
,1,1,'')
Exec('Update A set Results = B.Value
From #YourTable A
Join ( Select * from (values ' + #SQL + ')A([ID],[Value]) ) B
on A.ID = B.ID
')
Select *
From #YourTable
The Updated Table
id Calc Results
1 1+1 2
2 9*9 81
3 10/2 5
4 10-2 8
5 datediff(DAY,'2018-01-01',getdate()) 1012

Converting Traditional IF EXIST UPDATE ELSE INSERT into MERGE is not working?

I am going to use MERGE to insert or update a table depending upon ehether it's exist or not. This is my query,
declare #t table
(
id int,
name varchar(10)
)
insert into #t values(1,'a')
MERGE INTO #t t1
USING (SELECT id FROM #t WHERE ID = 2) t2 ON (t1.id = t2.id)
WHEN MATCHED THEN
UPDATE SET name = 'd', id = 3
WHEN NOT MATCHED THEN
INSERT (id, name)
VALUES (2, 'b');
select * from #t;
The result is,
id name
1 a
I think it should be,
id name
1 a
2 b
You have your USING part slightly messed up, that's where to put what you want to match against (although in this case you're only using id)
declare #t table
(
id int,
name varchar(10)
)
insert into #t values(1,'a')
MERGE INTO #t t1
USING (SELECT 2, 'b') AS t2 (id, name) ON (t1.id = t2.id)
WHEN MATCHED THEN
UPDATE SET name = 'd', id = 3
WHEN NOT MATCHED THEN
INSERT (id, name)
VALUES (2, 'b');
select * from #t;
As Mikhail pointed out, your query in the USING clause doesn't contain any rows.
If you want to do an upsert, put the new data into the USING clause:
MERGE INTO #t t1
USING (SELECT 2 as id, 'b' as name) t2 ON (t1.id = t2.id) --This no longer has an artificial dependency on #t
WHEN MATCHED THEN
UPDATE SET name = t2.name
WHEN NOT MATCHED THEN
INSERT (id, name)
VALUES (t2.id, t2.name);
This query won't return anything:
SELECT id FROM #t WHERE ID = 2
Because where is no rows in table with ID = 2, so there is nothing to merge into table.
Besides, in MATCHED clause you are updating a field ID on which you are joining table, i think, it's forbidden.
For each DML operations you have to commit (Marks the end of a successful the transaction)Then only you will be able to see the latest data
For example :
GO
BEGIN TRANSACTION;
GO
DELETE FROM HumanResources.JobCandidate
WHERE JobCandidateID = 13;
GO
COMMIT TRANSACTION;
GO

where exists - all - group by?

I use SQL Server 2008 R2.
I have a weird problem as following. I have a table as shown in
I need to write such a query like:
SELECT DISTINCT Field1
FROM MYTABLE
WHERE Field2 IN (96,102)
in this query, WHERE Field2 IN (96,102) gives me 96 or 102 or both!
More over, I would like to return rows that contains 96 and 102 at the same time!
Is there any suggestion? please write result oriented...
I have made a sqlfiddle for this..
create table a (id int, val int)
go
insert into a select 1, 22
insert into a select 1, 122
insert into a select 2, 22
insert into a select 3, 122
insert into a select 4, 22
insert into a select 4, 122
then select like this
select count(distinct id), id
from a
where val in (22, 122)
group by id
having count(id) > 1
EDIT: count(distinct id) will only show distinct counts..
EDIT:
Here's a sqlfiddle example (thanks to Mark Kremers):
http://sqlfiddle.com/#!3/df201/1
create table mytable (field1 int, field2 int)
go
insert into mytable values (199201, 84)
insert into mytable values (199201, 96)
insert into mytable values (199201, 102)
insert into mytable values (199201, 103)
insert into mytable values (581424, 96)
insert into mytable values (581424, 84)
insert into mytable values (581424, 106)
insert into mytable values (581424, 122)
insert into mytable values (687368, 79)
insert into mytable values (687368, 96)
insert into mytable values (687368, 102)
insert into mytable values (687368, 104)
insert into mytable values (687368, 106)
Here's the query:
select distinct a.field1 from
( select field1 from mytable where field2=96) a
inner join
( select field1 from mytable where field2=102) b
on a.field1 = b.field1
And here are the results:
FIELD1
199201
687368
Finally, here's a simplified version of the query (thans to pst):
select distinct a.field1 from mytable a
inner join mytable b
on a.field1 = b.field1
where a.field2=96 and b.field2=102
Use a self-join? Not the most tidy, but I think it works well for 2 values
SELECT *
FROM T R1
JOIN T R2 -- join table with itself
ON R1.F1 = R2.F1 -- where the first field is the same
WHERE R1.F2 = 96 AND R2.F2 = 102 -- and each has one of the required values
(T = Table, Rx = Relation Alias, Fx = Field)
If there can be an arbitrary number of fields, this can be solved as
CREATE TABLE #T (id int, val int)
GO
INSERT INTO #T (id, val)
VALUES
(1, 22), (1, 22), -- no, only 22 (but 2 records)
(2, 22), (2, 122), -- yes, both values (only)
(3, 122), -- no, only 122
(4, 22), (4,122), -- yes, both values ..
(4, 444), (4, null), -- and extra values
(5, 555) -- no, neither value
GO
-- Using DISTINCT over filtered results first, as
-- SQL Server 2008 does not support HAVING COUNT(DISTINCT F1, F2)
SELECT id
FROM (SELECT DISTINCT id, val
FROM #T
WHERE val IN (22, 122)) AS R1
GROUP BY id
HAVING COUNT(id) >= 2 -- or 3 or ..
GO
-- Or a similar variation, as can COUNT(DISTINCT ..)
-- in the SELECT of a GROUP BY
SELECT id
FROM (SELECT id, COUNT(DISTINCT val) as ct
FROM #T
WHERE val IN (22, 122)
GROUP BY id) AS R1
WHERE ct >= 2 -- or 3 or ..
GO
For larger IN (..) sizes, say above 20 values, it may be advisable to use a separate table or table-value and a JOIN for performance reasons.
Try from your original query:
SELECT DISTINCT Field1
FROM MYTABLE
WHERE rtrim(ltrim(cast(Field2 as varchar))) IN ('96','102')

Change a CTE SELECT to a table value user defined function

In an earlier post, I constructed a SQL that uses a CTE with the help from a SO contributor. I'd like now to encapsulate that SQL in a user defined function that returns a table but I am getting the error below.
Here's the code:
Alter FUNCTION GetDescendentSteps
(
#StepId INT
)
RETURNS TABLE
AS
RETURN
;WITH cteRecursion
AS (SELECT
StepId
,1 AS Level
FROM
Step
WHERE
StepId = #StepId
UNION ALL
SELECT
t.StepId
,c.Level + 1
FROM
Step t
INNER JOIN cteRecursion c
ON t.ParentStepId = c.StepId
)
SELECT
StepId,Level
FROM
cteRecursion
ORDER BY
Level,
StepId;
I get the error:
Msg 102, Level 15, State 1, Procedure GetDescendentSteps, Line 8
Incorrect syntax near ';'.
Note that line 8 is:
;WITH cteRecursion
..and that if I execute only the SQL beginning at line 8 (after I replace the variable #StepId with a literal).
Also, this simple example works:
ALTER FUNCTION GetDescendentSteps
(
#StepId INT
)
RETURNS TABLE
AS
RETURN
select 7 As Stepid,1 As Level
Remove the first ; and the order by clause.
Alter FUNCTION GetDescendentSteps
(
#StepId INT
)
RETURNS TABLE
AS
RETURN
WITH cteRecursion
AS (SELECT
StepId
,1 AS Level
FROM
Step
WHERE
StepId = #StepId
UNION ALL
SELECT
t.StepId
,c.Level + 1
FROM
Step t
INNER JOIN cteRecursion c
ON t.ParentStepId = c.StepId
)
SELECT
StepId,Level
FROM
cteRecursion

Can we use Select query output as Column alias

i need a select statements output as a columns's alias
is it possible
examples
select columnname as (select value from tablename) from tablename
output
values
1
2
3
no you can't, see this:
declare #a table (rowvalue varchar(20))
insert #a values ('aaa')
insert #a values ('bbb')
insert #a values ('ccc')
insert #a values ('ddd')
declare #x table (id int,rowvalue varchar(20))
insert #x values (1, 'wowwee')
insert #x values (2, 'noooo!')
select a.rowvalue as (select rowvalue from #x where id=1)
from #a a
OUTPUT:
Msg 102, Level 15, State 1, Line 11
Incorrect syntax near '('.
Msg 156, Level 15, State 1, Line 12
Incorrect syntax near the keyword 'from'.
you'll have to use dynamic sql for this.
EDIT to show dynamic sql:
declare #SQL varchar(500)
,#ColumnName varchar(20)
create table #a (rowvalue varchar(20))
insert #a values ('aaa')
insert #a values ('bbb')
insert #a values ('ccc')
insert #a values ('ddd')
declare #x table (id int,rowvalue varchar(20))
insert #x values (1, 'wowwee')
insert #x values (2, 'noooo!')
SELECT #ColumnName=rowvalue FROM #x where id=1
set #SQL='select a.rowvalue as '+#ColumnName+' from #a a'
exec(#SQL)
OUTPUT:
wowwee
--------------------
aaa
bbb
ccc
ddd
(4 row(s) affected)
Try this
Select (Select value from Tablename) as Columnname from Tablename
The output should resemble the following
ColumnName
- 1
- 2
- 3
I think you have to quit de AS word in tsql, I mean:
select column name (select value from tablename) from tablename