Insert multiple rows in a single query using results of a select statement - sql

I am looking for a compact way to do this - insert multiple rows into a table with values from multiple columns of a row from another table. My destination table is really a list with a single column:
declare #stringList table
(
val nvarchar(100)
)
This is how we can insert multiple rows:
INSERT INTO #stringList ( val ) VALUES
Val1, Val2, Val3, ...
This is how we insert from a select:
INSERT INTO #stringList
SELECT col1 FROM table1 where id=something
But I cannot seem to find a way to use both at the same time.
I can select from one column:
insert into #stringList (val)
select col1 from table1 where id=something
But it doesn't extend to multiple columns:
insert into #stringList (val)
select col1, col2 from table1 where id=something
--The select list for the INSERT statement contains more items than the insert list. The number of SELECT values must match the number of INSERT columns.
I have tried various ways including using parentheses, but the syntax is not accepted:
insert into #stringList (val)
(select col1 from table1 where id=something,
select col2 from table1 where id=something
Any idea if what I want is doable?

You can unpivot using cross apply:
insert into #stringList (val)
select v.col
from table1 t1 cross apply
(values (t1.col1), (t1.col2)) v(col)
where t1.id = something;

Related

Select rows with same data in columns

I have a SQL Server database with a table with 20 columns. These columns have data as agree or disagree. Now I want to show rows in these columns which have "agree" data in them. I can use where clause but it is a time consuming task for 20 columns. I am looking for a SQL query which does this task.
You can use in:
select t.*
from t
where 'agree' in (col1, col2, ... col20);
There is no shortcut for this type of scenarios, If you want to compare all the columns, you have to explicitly mention each and every column like .
WHERE Col1='agree' AND Col2="agree"....
To avoid coding, you may go with dynamic query creation or creating a function, but ultimately it will be executed as same query comparing all the columns.
What about JOIN ?
If u have such a complex logic, best practices advise to keep data in different tables.
Here's some simplified example code that tests out several methods to return records that may or may not agree.
Just for the fun of it actually.
declare #T table (id int identity(1,1) primary key, col1 varchar(30), col2 varchar(30), col3 varchar(30));
insert into #T (col1, col2, col3) values
('agree','agree','agree'),
('agree','disagree','disagree'),
('agree','disagree',null),
('disagree','disagree','disagree'),
('disagree','disagree',null),
(null,null,null);
select 'OR' as method, * from #T
where (col1='agree' OR col2='agree' OR col3='agree');
select 'AND' as method, * from #T
where (col1='agree' AND col2='agree' AND col3='agree');
select 'IN' as method, * from #T
where 'agree' IN (col1, col2, col3);
select 'NOT IN' as method, * from #T
where 'agree' NOT IN (col1, col2, col3);
select 'LIKE' as method, * from #T
where CONCAT('-',col1,'-',col2,'-',col3,'-') LIKE '%-agree-%';
select 'NOT LIKE' as method, * from #T
where CONCAT('-',col1,'-',col2,'-',col3,'-') NOT LIKE '%-agree-%';
select 'ALL' as method, * from #T
where 'agree' = ALL(select col from (values (col1),(col2),(col3))q(col));
select 'SOME' as method, * from #T
where 'agree' = SOME(select col from (values (col1),(col2),(col3))q(col));
select 'ANY' as method, * from #T
where 'agree' = ANY(select col from (values (col1),(col2),(col3))q(col));
select 'EXISTS' as method, * from #T
where EXISTS (
select 1
from (values (col1),(col2),(col3))q(col)
where col = 'agree'
);
select 'NOT EXISTS' as method, * from #T
where NOT EXISTS (
select 1
from (values (col1),(col2),(col3))q(col)
where col = 'agree'
);

Convert each column of a record into separate record

I have a record:
DECLARE #Tbl AS TABLE(Col1 VARCHAR(10), Col2 VARCHAR(10), Col3 VARCHAR(10));
INSERT INTO #Tbl
VALUES('Val1', 'Val2', 'Val3')
-- Source Record
SELECT Col1, Col2, Col3 FROM #Tbl
Result: Val1 Val2 Val3
I want result of each column as separate two column records like first column will become the title of source column and second column should be the value of source column like the result of below query in which I have achieved the result by UNION ALL :
--Query for Target Result
SELECT 'Col1' AttributeTitle, CONVERT(VARCHAR, Col1) AttributeValue FROM #Tbl
UNION ALL SELECT 'Col2' AttributeTitle, CONVERT(VARCHAR, Col2) AttributeValue FROM #Tbl
UNION ALL SELECT 'Col3' AttributeTitle, CONVERT(VARCHAR, Col3) AttributeValue FROM #Tbl
Problem in this query is I have to explicitly define the columns, is there any way that it should dynamically get the columns names and their values?
You could use UNPIVOT but you still need to know the names of the columns.
SELECT ColumnName, ValueName
FROM (SELECT * FROM #Tbl) AS Data
UNPIVOT
( ValueName
FOR ColumnName IN (Col1, Col2, Col3)
) AS PivottedOutput
I like the apply method for unpivoting in SQL Server:
select v.*
from #tbl t cross apply
(values ('col1', col1),
('col2', col2),
('col3', col3)
) v(AttributeTitle, AttributeValue);
This simplifies the query but it does not directly answer the question.
If you want a variable number of columns, then you are going to have to use dynamic SQL. This is a bit cumbersome on a real table. However, with a table variable or a temporary table, you have the additional issue of scoping rules -- the name of the table will not be in scope when you execute the statement.

SQL Server: Select from two tables and insert into one

I have a stored procedure with two table variables (#temp and #temp2).
How can I select the values from both temp tables (Both table variables contain one row) and insert them all in one table ?
I tried the following but this didn't work and I got the error that the number of SELECT and INSERT statements does not match.
DECLARE #temp AS TABLE
(
colA datetime,
colB nvarchar(1000),
colC varchar(50)
)
DECLARE #temp2 AS TABLE
(
colD int
)
...
INSERT INTO MyTable
(
col1,
col2,
col3,
col4
)
SELECT colD FROM #temp2,
colA FROM #temp,
colB FROM #temp,
colC FROM #temp
Many thanks for any help with this, Tim.
As both table variables have a single row you can cross join them.
INSERT INTO MyTable
(col1,
col2,
col3,
col4)
SELECT t.colA,
t.colB,
t.colC,
t2.colD
FROM #temp t
CROSS JOIN #temp2 t2
you should use this if you have only single row in both table #temp and #temp2, because this is a cartesian product.
INSERT INTO MyTable(col1,col2,col3,col4)
SELECT t.colA,
t.colB,
t.colC,
t2.colD
FROM #temp t,#temp2 t2

How to convert a column header and its value into row in sql?

I have a table with columns say col1, col2, col3. The table has many rows in it.
Let's assume val1, val2, val3 is one such row. I want to get the result as
Col1, Val1
Col2, Val2
Col3, Val3
That is 3 rows - one for each column and its value.
I am using SQL Server 2008. I read about pivots. Are pivots a way to solve this problem? Can someone route me to some examples or solutions how to solve this problem?
Thanks a lot
Maybe something like this:
Test data
DECLARE #T TABLE(Col1 INT, Col2 INT, Col3 INT)
INSERT INTO #T
VALUES (1,1,1)
Query
SELECT
*
FROM
(
SELECT
t.Col1,
t.Col2,
t.Col3
FROM
#T AS t
) AS SourceTable
UNPIVOT
(
Value FOR Col IN
(Col1,Col2,Col3)
) AS unpvt
Output
1 Col1
1 Col2
1 Col3
To do this kind of thing read the following: Using PIVOT and UNPIVOT
Pivot function allow you to convert row values in from of column..
Also check : Dynamic Pivoting in SQL Server
Example :
create table #temptable(colorname varchar(25),Hexa varchar(7),rgb varchar(1), rgbvalue tinyint)
GO
insert into #temptable values('Violet','#8B00FF','r',139);
insert into #temptable values('Violet','#8B00FF','g',0);
insert into #temptable values('Violet','#8B00FF','b',255);
insert into #temptable values('Indigo','#4B0082','r',75);
insert into #temptable values('Indigo','#4B0082','g',0);
insert into #temptable values('Indigo','#4B0082','b',130);
insert into #temptable values('Blue','#0000FF','r',0);
insert into #temptable values('Blue','#0000FF','g',0);
insert into #temptable values('Blue','#0000FF','b',255);
SELECT colorname,hexa,[r], [g], [b]
FROM
(SELECT colorname,hexa,rgb,rgbvalue
FROM #temptable) AS TableToBePivoted
PIVOT
(
sum(rgbvalue)
FOR rgb IN ([r], [g], [b])
) AS PivotedTable;
Create a temproary table:
CREATE TABLE #table2
(
name NCHAR,
bonus INT
)
Now Select and execute the below statement if there is an empty.
SELECT * FROM #table2
INSERT INTO #table2 (name,bonus) VALUES ('A',10)
INSERT INTO #table2 (name,bonus) VALUES ('B',20)
INSERT INTO #table2 (name,bonus) VALUES ('C',30)
After insert the values into table. select and execute the below line if you get records:
SELECT * FROM #table2
Input:
name bonus
A 10
B 20
C 30
Change the input into like this result
Result:
Cost A B C
Bonus 10 20 30
By using this code:
SELECT 'Bonus' AS Cost,
[A],[B],[C]
FROM
(SELECT name, Bonus
FROM #table2) AS TempTbl
PIVOT
(
AVG(bonus)
FOR [name] IN ([A],[B],[C])
) AS PivotTable;

Grouping result according to one column in sql

I have a sql statement like
SELECT column1, column2,column3, column4 FROM table1 GROUP BY column3
or
SELECT * FROM table1 GROUP BY column3
I want a result which is grouped according to column3 and also has other columns. But it gives an error.What should I do? thanks..
If i understand your expected end result correctly,
try using ORDER instead of GROUP
if however that does not give you your desired output, i apologize.
SELECT column1, column2,column3, column4
FROM table1
ORDER BY column3
SELECT *
FROM table1
ORDER BY column3
What you are trying to do is an undefined behavior. When you specify GROUP BY on a column, there can be multiple values in other columns. There is no sane way for the database to figure out what values to show.
PARTITION is probably what you are looking for. Check this link: http://msdn.microsoft.com/en-us/library/ms189461.aspx
Grouping applies to aggregate functions such as SUM(). It doesn't make sense to group individual fields.
SELECT SUM(col1), MAX(col2), col3 from t1 group by col3
I haven't understood your question exactly and what for you need this query, but maybe you can use this one:
/*t-sql example*/
create table #T (id int identity(1,1), col1 varchar(5), col2 varchar(5), col3 varchar(6))
insert #T (col1,col2,col3) values ('aaa','a1e','group1')
insert #T (col1,col2,col3) values ('bbb','a2e','group1')
insert #T (col1,col2,col3) values ('ccc','a3e','group1')
insert #T (col1,col2,col3) values ('ddd','a4e','group2')
insert #T (col1,col2,col3) values ('eee','a5e','group2')
insert #T (col1,col2,col3) values ('fff','a6e','group3')
select id,col1,col2,#T.col3,subq.cnt from #T
join
(select col3, COUNT(*) as 'cnt' from #T group by col3) as subq
on
#T.col3 = subq.col3
I have used sub-query, but you can use temporary table or WITH. Also, I have used "count" for aggregation just for example.
Max