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;
I have a temp table with one column of xml type.
How can I write a single SELECT query to list all unique values of attribute 'z'
CREATE TABLE #TEST3 ([Data] XML)
INSERT INTO #TEST3 VALUES ('<r><a z="1" /> <a z="2" /></r>')
INSERT INTO #TEST VALUES ('<r><b z="2" /><b z="3" /></r>')
INSERT INTO #TEST3 VALUES ('<r><c z="3"><c z="4" /></c></r>')
Select
Distinct t.m.value( '#z[1]', 'varchar(max)' ) ZAttribute
From
#Test3 tempTable
Cross Apply tempTable.Data.nodes( '/your/node/path/here' ) t(m)
I have a sql table that has two columns id and name. I have list of names about 20 and I need to write a query that checks if name exists before insert.
Is there a better way of doing this rather then just having the below query 20 times but with different names (I need do this in t-sql):
IF NOT EXISTS(SELECT*
FROM mytable
WHERE name = 'Dan')
BEGIN
INSERT INTO mytable
(name)
VALUES ('dan')
END
INSERT INTO MyTable (Name)
SELECT NewNames.Name
FROM ( VALUES ('Name1'), ('Name2'), ('Name3') ) AS NewNames (Name)
WHERE NOT EXISTS ( SELECT 1
FROM MyTable AS MT
WHERE MT.Name = NewNames.Name );
I think you could use a merge statement:
MERGE INTO myTable AS Target
USING (VALUES ('name1'),('name2'),('...')) AS source (NAME)
ON Target.NAME = Source.NAME
WHEN NOT MATCHED BY TARGET THEN
INSERT (NAME) VALUES (name)
You can filter values with NOT EXISTS
INSERT INTO myTable (
Name
)
SELECT DISTINCT
Name
FROM (
VALUES ('Name 1'),
('Name 2')
) AS NewNames(Name)
WHERE
NOT EXISTS (SELECT 1 FROM TargetTable WHERE myTable.Name = NewNames.Name)
If your new names are in another table, you can change the select query in the above one.
Please note, that the DISTINCT keyword is necessary to filter out the duplications in the source data.
I would do this using insert:
with names as (
select 'Dan' as name union all
select 'name2' union all
. . .
)
insert into myTable(name)
select distinct name
from myTable
where not exists (select 1 from mytable t2 where t2.name = t.name);
Note: you may want to create a unique index on mytable(name) so the database does the checking for duplicates.
untested so there might be some minor errors:
merge into mytable x
using (
values ('name1')
, ('name2')
, ...
, ('namen')
) as y (name)
on x.name = y.name
when not matched then
insert (name)
values (y.name)
INSERT INTO MyTable (Name)
SELECT Name FROM
(
VALUES ('Name 1'),
('Name 2')
) AS Names(Name)
WHERE Name NOT IN
(
SELECT Name FROM MyTable
)
INSERT IGNORE INTO myTable (column1, column2) VALUES (val1, val2),(val3,val4),(val5,val6);
INSERT IGNORE will allow skip on duplicate values
I need to display a query output in a horizontal manner. I have some example data
create table TestTable (id number, name varchar2(10))
insert into TestTable values (1, 'John')
insert into TestTable values (2, 'Mckensy')
insert into TestTable values (3, 'Valneech')
insert into TestTable values (4, 'Zeebra')
commit
select * from TestTable
This gets the output in a vertical view.
ID Name
==========
1 John
2 Mckensy
3 Valneech
4 Zeebra
However, I need to display it horizontally.
ID 1 2 3 4
Name John Mckensy Valneech Zeebra
How can one do this?
To pivot, you should use the pivot clause of the select statement:
select *
from testtable
pivot ( max(name)
for id in (1,2,3,4)
)
This is not particularly pretty to do in SQL, so you should consider carefully whether this is what you want to do. I normally use Oracle Base for pivoting examples but there are many out there.
Here's a little SQL Fiddle to demonstrate.
Maybe it will help you:
select 'id', LISTAGG(id, ' ') WITHIN GROUP (ORDER BY name)
from testtable
union
select 'name', LISTAGG(name, ' ') WITHIN GROUP (ORDER BY name)
from testtable
EDIT:
or with pivot:
create table TestTable2 (id varchar2(30), name varchar2(10));
insert into TestTable2 values ('id', 'name');
insert into TestTable2
select cast(id as varchar2(30)) as id , name
from testtable
select *
from testtable2
pivot ( max(name)
for id in ('id',1,2,3,4)
)
PIVOT operator is what you are looking for.
I have
SELECT * FROM Table1 WHERE Col1 IN(4,2,6)
I want to select and return the records with the specified order which i indicate in the IN clause
(first display record with Col1=4, Col1=2, ...)
I can use
SELECT * FROM Table1 WHERE Col1 = 4
UNION ALL
SELECT * FROM Table1 WHERE Col1 = 6 , .....
but I don't want to use that, cause I want to use it as a stored procedure and not auto generated.
I know it's a bit late but the best way would be
SELECT *
FROM Table1
WHERE Col1 IN( 4, 2, 6 )
ORDER BY CHARINDEX(CAST(Col1 AS VARCHAR), '4,2,67')
Or
SELECT CHARINDEX(CAST(Col1 AS VARCHAR), '4,2,67')s_order,
*
FROM Table1
WHERE Col1 IN( 4, 2, 6 )
ORDER BY s_order
You have a couple of options. Simplest may be to put the IN parameters (they are parameters, right) in a separate table in the order you receive them, and ORDER BY that table.
The solution is along this line:
SELECT * FROM Table1
WHERE Col1 IN(4,2,6)
ORDER BY
CASE Col1
WHEN 4 THEN 1
WHEN 2 THEN 2
WHEN 6 THEN 3
END
select top 0 0 'in', 0 'order' into #i
insert into #i values(4,1)
insert into #i values(2,2)
insert into #i values(6,3)
select t.* from Table1 t inner join #i i on t.[in]=t.[col1] order by i.[order]
Replace the IN values with a table, including a column for sort order to used in the query (and be sure to expose the sort order to the calling application):
WITH OtherTable (Col1, sort_seq)
AS
(
SELECT Col1, sort_seq
FROM (
VALUES (4, 1),
(2, 2),
(6, 3)
) AS OtherTable (Col1, sort_seq)
)
SELECT T1.Col1, O1.sort_seq
FROM Table1 AS T1
INNER JOIN OtherTable AS O1
ON T1.Col1 = O1.Col1
ORDER
BY sort_seq;
In your stored proc, rather than a CTE, split the values into table (a scratch base table, temp table, function that returns a table, etc) with the sort column populated as appropriate.
I have found another solution. It's similar to the answer from onedaywhen, but it's a little shorter.
SELECT sort.n, Table1.Col1
FROM (VALUES (4), (2), (6)) AS sort(n)
JOIN Table1
ON Table1.Col1 = sort.n
I am thinking about this problem two different ways because I can't decide if this is a programming problem or a data architecture problem. Check out the code below incorporating "famous" TV animals. Let's say that we are tracking dolphins, horses, bears, dogs and orangutans. We want to return only the horses, bears, and dogs in our query and we want bears to sort ahead of horses to sort ahead of dogs. I have a personal preference to look at this as an architecture problem, but can wrap my head around looking at it as a programming problem. Let me know if you have questions.
CREATE TABLE #AnimalType (
AnimalTypeId INT NOT NULL PRIMARY KEY
, AnimalType VARCHAR(50) NOT NULL
, SortOrder INT NOT NULL)
INSERT INTO #AnimalType VALUES (1,'Dolphin',5)
INSERT INTO #AnimalType VALUES (2,'Horse',2)
INSERT INTO #AnimalType VALUES (3,'Bear',1)
INSERT INTO #AnimalType VALUES (4,'Dog',4)
INSERT INTO #AnimalType VALUES (5,'Orangutan',3)
CREATE TABLE #Actor (
ActorId INT NOT NULL PRIMARY KEY
, ActorName VARCHAR(50) NOT NULL
, AnimalTypeId INT NOT NULL)
INSERT INTO #Actor VALUES (1,'Benji',4)
INSERT INTO #Actor VALUES (2,'Lassie',4)
INSERT INTO #Actor VALUES (3,'Rin Tin Tin',4)
INSERT INTO #Actor VALUES (4,'Gentle Ben',3)
INSERT INTO #Actor VALUES (5,'Trigger',2)
INSERT INTO #Actor VALUES (6,'Flipper',1)
INSERT INTO #Actor VALUES (7,'CJ',5)
INSERT INTO #Actor VALUES (8,'Mr. Ed',2)
INSERT INTO #Actor VALUES (9,'Tiger',4)
/* If you believe this is a programming problem then this code works */
SELECT *
FROM #Actor a
WHERE a.AnimalTypeId IN (2,3,4)
ORDER BY case when a.AnimalTypeId = 3 then 1
when a.AnimalTypeId = 2 then 2
when a.AnimalTypeId = 4 then 3 end
/* If you believe that this is a data architecture problem then this code works */
SELECT *
FROM #Actor a
JOIN #AnimalType at ON a.AnimalTypeId = at.AnimalTypeId
WHERE a.AnimalTypeId IN (2,3,4)
ORDER BY at.SortOrder
DROP TABLE #Actor
DROP TABLE #AnimalType
ORDER BY CHARINDEX(','+convert(varchar,status)+',' ,
',rejected,active,submitted,approved,')
Just put a comma before and after a string in which you are finding the substring index or you can say that second parameter.
And first parameter of CHARINDEX is also surrounded by , (comma).