Combine fields in SQL Server - sql-server

How to combine rows in SQL Server 2000

Have you tried using FOR XML RAW in SQL Server 2000?

You can create a user defined function to perform the string concatenation for each ID value.
create table t (id int,start varchar(100),finish varchar(100))
insert into t
select 1,'Start_Main', '' union all
select 1,'Start_Submain1', '' union all
select 2,'Start_Main', '' union all
select 2,'Start_Submain2', 'End_Submain2' union all
select 2,'Start_Submain3', 'End_Submain3' union all
select 2,'Start_Submain1', '' union all
select 2,'Start_Submain4', 'End_Submain4'
Select * from t
go
/* User Defined Function to perform string concatenation per ID */
create function udfStringConcat (#ID int)
returns varchar(500)
as
begin
declare #x varchar(500)
set #x = ''
select #x = #x + t.start + ',' + case when t.finish <> '' then t.finish + ',' else t.finish end
from t
where t.id = #ID
select #x = #x + 'End_Submain1,End_Main'
return #x
end
go
select id, dbo.udfStringConcat(id)
from t
group by id
go
drop function udfStringConcat
drop table t
go

Related

Showing "Invalid object name " in sqlServer?

While Executing the Following query it showing the Invalid object name '#temp1'. can any body knows the error occurred due to which reason this is my orginal code i used to fetch code , her differnt tables are formed i need to get the sum of the each row of each table
DECLARE #t TABLE (
id int IDENTITY(1,1),
BranchName nvarchar(max)
)
DECLARE #n int = 0,
#i int = 1,
#BranchName nvarchar(max),
#sql nvarchar(max),
#columns nvarchar(max)
INSERT INTO #t
SELECT DISTINCT BranchName
FROM ALX_Branches
SELECT #n = ##ROWCOUNT
WHILE #n >= #i
BEGIN
SELECT #BranchName = BranchName
FROM #t
WHERE id = #i
SELECT #columns = (
SELECT DISTINCT ','+QUOTENAME([SubInventory])
FROM #MyTempTable
WHERE [BranchName] = #BranchName
FOR XML PATH('')
)
SELECT #sql = N'--
SELECT * into #temp1
FROM (
SELECT [BranchID],
[SubInventory],
[Product],
[Stock]
FROM #MyTempTable
WHERE [BranchName] = ''' +#BranchName +'''
) as t
PIVOT (
MAX([Stock]) FOR [SubInventory] IN ('+STUFF(#columns,1,1,'')+')
) as pvt'
EXEC sp_executesql #sql
select * from #temp1
Firstly, there is no need for creating #temp1 table before.
because you are using "Select * into" that already create table within it.
Suppose type this note as a comment, but I don't have enough reputation score.
The reason of
Invalid object name '#temp1'
is: the variable #sql is NULL because #temp1 is not created yet via "Select * into" clause.
so append selecting from #temp1 within dynamic sql as the following:
SELECT #sql = N'--
SELECT * into #temp1
FROM (
SELECT [BranchID],
[SubInventory],
[Product],
[Stock]
FROM #MyTempTable
WHERE [BranchName] = ''' +#BranchName +'''
) as t
PIVOT (
MAX([Stock]) FOR [SubInventory] IN ('+STUFF(#columns,1,1,'')+')
) as pvt
select * from #temp1 '
EXEC sp_executesql #sql

How to store math formula in SQL Server

I have a table contains the following data:
ID | expression
----|------------
1 | select 1+9
2 | select 6+23+3
----|------------
I need a query to get the result:
ID | expressionValue
----|------------
1 | 10
2 | 32
----|------------
You can try like this:
declare #x nvarchar(100)
select #x = expression from myTable where id = 1
EXECUTE sp_executesql #x
And if you want this to be done for all the rows of your table then try to create a cursor and execute it for your column like this:
DECLARE #myRes TABLE
(
ID INT ,
expression NVARCHAR(100)
)
DECLARE #temp TABLE ( ID INT )
DECLARE #ID INT ,
#expression NVARCHAR(100)
DECLARE cur CURSOR FAST_FORWARD READ_ONLY
FOR
SELECT ID , expression FROM myTable
OPEN cur
FETCH NEXT FROM cur INTO #ID, #expression
WHILE ##FETCH_STATUS = 0
BEGIN
DELETE FROM #temp
INSERT INTO #temp
EXEC ( #expression )
INSERT INTO #myRes
VALUES ( #ID, ( SELECT * FROM #temp ) )
FETCH NEXT FROM cur INTO #ID, #expression
END
CLOSE cur
DEALLOCATE cur
SELECT * FROM #myRes
Output:
If you got only + and - in formulas - then you can use XML.query:
SELECT ID,
CAST(
REPLACE(
REPLACE(
REPLACE(expression,'select ','<v><d>')
,'+','</d><d>')
,'-','</d><d>-') + '</d></v>'
as xml).query('for $s in /v return data(fn:sum($s/d))') as expressionValue
FROM YourTable
Output:
ID expressionValue
1 10
2 32
Also you can avoid using dynamic SQL to execute SELECT formula statements and use more secure way with XML.query:
CREATE TABLE #Results ( --Table to store results
ID int,
expressionValue nvarchar(max)
)
DECLARE #sql nvarchar(max) --will hold the dynamic SQL query
SELECT #sql = COALESCE(#sql,'DECLARE #x xml = ''''; INSERT INTO #Results ') +
'SELECT '+CAST(ID as nvarchar(max))+' as ID,
CAST(#x.query('''+REPLACE(expression,'select ','')+''') as nvarchar(max)) UNION '
FROM #YourTable --query generation
SELECT #sql = LEFT(#sql,LEN(#sql)-LEN(' UNION '))
If you make PRINT #sql you will get something like:
DECLARE #x xml = '';
INSERT INTO #Results
SELECT 1 as ID,
CAST(#x.query('1+9') as nvarchar(max))
UNION
SELECT 2 as ID,
CAST(#x.query('6+23+3') as nvarchar(max))
Then execute:
EXEC sp_executesql #sql
Then you can select from #Results table:
SELECT *
FROM #Results
Output:
ID expressionValue
1 10
2 32
Try this...
create table expr(id int,epres varchar(max))
insert into expr values(1,'select 2+2')
insert into expr values(2,'select 2-1')
declare #sql varchar(max),#id int
select top 1 #sql = epres,#id=id from expr where epres is not null order by id
while ##rowcount > 0
begin
exec(#sql)
select top 1 #sql = epres ,#id=id from expr where id > #id order by id;
end;

Create string with embedded quotes in SQL

I run several queries that use a list of character values in the where clause, e.g.,
select *
from table1
where col1 in ('a','b','c')
The character list changes frequently, so I want to store the string in a variable and reference the variable in all of the queries instead of maintaining several copies of the string. I've tried the following but the query returns zero rows.
declare #str varchar(50)
select #str = '''a''' + ',' + '''b'''+ ',' + '''c'''
select *
from table1
where col1 in (#str)
#str has the value 'a','b','c' but for some reason, SQL Server doesn't recognize it. How do I build a string and store it in a variable that works with the in keyword?
The IN construct in SQL as a set lookup, not a string lookup. Your single string value of "'a','b','c'" is exactly what it's looking for when you say where col1 in (#str)... as Fredou mentioned in comments.
Instead you want to pass in a set of values by using a table variable (or a temp table):
declare #tabIn table ( val varchar(10) )
insert #tabIn
(val) values
('a'), ('b'), ('c')
select *
from table1
where
col1 in (select val from #tabIn)
or, alternatively, just do a straight join:
declare #tabIn table ( val varchar(10) )
insert #tabIn
(val) values
('a'), ('b'), ('c')
select *
from table1 t1
join #tabIn t2 on
t1.col1 = t2.val
It is possible to create a string with embedded quotes. As Fredou and ChrisS mentioned, #str is considered a single string. If the #str value is concatenated with the rest of your select statement and then executed, you will achieve the your desired results. SQL Fiddle example.
declare #str varchar(50)
declare #sql varchar(MAX)
select #str = '''a''' + ',' + '''b'''+ ',' + '''c'''
Select #sql = 'SELECT * FROM table1 WHERE col1 IN (' + #str + ')'
Exec(#sql)
Results using #str = '''a''' + ',' + '''b'''+ ',' + '''c'''
Results using #str = '''a''' + ',' + '''b'''

Query All Views In Database

I am looking to return a view name and all record ID's where billingAddress != shippingAddress to further review. I need to query all views in one database. This is my thought process and if their is a better way or faster way to write the query by all means help me out!
What I am stuck on is how to return the view name with the recordID?
Create Table #T (ID Int Identity Not Null, ViewNames VARCHAR(1000)
Create Table #2 (viewNames varchar(1000))
Insert Into #T (ViewNames)
Select '['+C.Table_Catalog+'].['+C.Table_Schema+'].['+C.Table_Name+']' TableName
FROM Information_Schema.Columns c
Join information_schema.Tables T on C.Table_Catalog = T.Table_Catalog
AND C.Table_Schema = T.Table_Schema
AND C.Table_Name = T.Table_Name
Where T.Table_Type = 'View'
Group By '['+C.Table_Catalog+'].['+C.Table_Schema+'].['+C.Table_Name+']'
---Now this is the piece that I am stuck on as I do not know how to insert the view name into the table as well on each iteration
Declare #N int, #Str nvarchar(2000), #viewname nvarchar(2000), #MaxID int
Set #N = 1
Select #MaxID = Max(ID)
From #T
While (#N<#MaxID)
Begin
Select #viewname= viewname
From #T
Set #Str = ' Insert Into #2(viewname)
Select Top 1 '''+#viewname+'''
From '+#viewname+'
where exists(Select recordID from '+#viewname+' where [shipaddress] != [billaddress] ) '
Exec sp_eecutesql #str
Set #N = #N + 1
End
Select * from #t
Try changing your dynamic query like this.
You said you wanted the view name, and record id, so you need to add a column to #2
SET #Str = 'INSERT INTO #2(viewname, recordid)
SELECT ''' + quotename(#viewname) + ''', recordID
FROM '+ quotename(#viewname) + '
WHERE [shipaddress] != [billaddress]'
EXEC sp_executesql #str
Unless you're sure of the object names, you should try and use quotename when building up dynamic SQL
You do have a problem in your logic though...
You are missing a where clause in the query that assigns the value to #viewname
Try this...
SELECT #viewname= viewname
FROM #T
WHERE ID = #N
I do not understand sql returns set of rows so your variable #viewname can not be assigned value row by row. By default your #viewname will be assigned last row of table T.

Querying multiple tables in TSQL where table name comes from another table

I need to select from table where the the table name suffix are from another table, like this :
declare #value nvarchar(3),
#table nvarchar(1000),
#SQLST NVARCHAR(255);
set #value = N'select column1 from tableX';
EXEC #value
set #table ='partoftableY'
Set #SQLST ='select * from' +#tabel + #value -- here I create the table name
However there are multiple values in TableX (0-999) and so this doesn't work. Do I need a For Each type construct.
here in an example I created with two tables (partoftableY1 & partoftableY2) with different data in each
/*
create table tableX (column1 int);
insert into tablex
select 1
union all select 2;
create table partoftableY1 (data nvarchar(50));
create table partoftableY2 (data nvarchar(50));
insert into partoftableY1 select 'hey 1 here';
insert into partoftableY2 select 'hey 2 here';
*/
declare #sql nvarchar(max)
-- use the ability of SQL to build up string of all the sql you need to run
set #sql = 'select data from (select '''' as data'
select #sql = COALESCE(#sql + ' union all ', '')
+ 'select data from partoftableY'
+ cast(column1 as nvarchar(4)) from tableX
select #sql = #sql + ') X where data <>'''''
-- DEBUG for seeing what SQL you created
print #sql
-- Now execute the SQL
exec sp_executesql #sql= #sql
which gives me the results of
hey 1 here
hey 2 here
You will need to adjust it for types of your data, but this should give you the main idea
For reference here is the sql that was created and executed:
select data
from (
select '' as data
union all select data from partoftableY1
union all select data from partoftableY2
) X
where data <>''
N.B.
I put formatted it for easier reading, as it's actually created as one long line
I used selet data and not select * as the number of columns needs to be the same for each select in the union. You will need to select the columns you need and then make changes ensure that all the columns in the selects in the union are the same.
There is a dummy select at the top of the union to make the union code easy - no conditionals needed as whether the union all needs to present
I used the out select over the whole union to enable you to get sid of the dummy select
You can try this
DECLARE #SQLST NVARCHAR(max)='';
DECLARE #select nvarchar(max)=N'select * from partoftableY'
DECLARE #union nvarchar(max)=N'
UNION ALL
'
SELECT #SQLST=#select+column1+#union
FROM tablex
SELECT #SQLST=substring(#SQLST,1,LEN(#SQLST)-11)
EXEC sp_executesql #SQLST

Resources