Inserting new values in a table if SQL had Dictionary and for-each - sql

Let's say my table of myTable has a column1 that has some values already in it.
Now I am given some new values that I should put in a newly created column named 'column2' .
These are one to one associated together and unique. So for example:
column1 | column2
-----------------
'ABCHi' | 'newOH'
-----------------
'TER12' | 'Meow2'
-----------------
'WhatE' | 'BMW26'
-----------------
So I could say like:
Update myTable SET column2 = 'newOH' WHERE column1 = 'ABCHi'
and do that for each of those rows ( I have 32 of them to do ).
But I thought maybe there is a "nicer" way of doing this? Like if it was C# I could say populate a dictionary and then do a for-each loop!

You can use a Table Value Constructor:
declare #Samples as Table ( Column1 VarChar(10), Column2 VarChar(10) );
-- Initialize the sample data.
insert into #Samples ( Column1 ) values
( 'ABCHi' ), ( 'TER12' ), ( 'WhatE' )
select * from #Samples;
-- Update the second column.
update OSamples
set Column2 = NSamples.Column2
from #Samples as OSamples inner join
( values
( ( 'ABCHi' ), ( 'newOH' ) ),
( ( 'TER12' ), ( 'Meow2' ) ),
( ( 'WhatE' ), ( 'BMW26' ) )
) as NSamples( Column1, Column2 )
on OSamples.Column1 = NSamples.Column1;
select * from #Samples;
DBfiddle.

you could create the "Dictionary" as an inline view using the With clause.
here is the fiddle https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=c0e1393785082fd5cd9352d513b76af6
with Dictionary as(
select 'ABCHi' as column1, 'newOH' as column2
union all
select 'TER12' as column1, 'Meow2' as column2
union all
select 'WhatE' as column1, 'BMW26' as column2
)
UPDATE t
SET t.column2=dictionary.column2
FROM mytable t JOIN Dictionary ON t.column1 = Dictionary.column1

Related

Can I use lag function in an update function to update a variable table

I have this #variable table with an initial row. I'd like to update the following rows based on that first row.
DECLARE #varTable1 Table
(
[id] [int],
[field1] [decimal](18,4)
)
INSERT INTO #varTable1
VALUES
(1,20),
(1,NULL),
(1,NULL),
(1,NULL)
SELECT * FROM #varTable1
Let's just say I want to multiply field1 by 2. So the expected values following inital row would be
1 20
2 40
3 60
4 80
One way is to get the min value and multiple it by a row number - assuming your id column should actually be incrementing rather than all 1's e.g.
WITH cte AS (
SELECT *
, MIN(field1) OVER () * ROW_NUMBER() OVER (ORDER BY id ASC) newField1
FROM #varTable1
)
UPDATE cte SET field1 = newField1;
I guess id is important so you have to multiple field of same id
DECLARE #varTable1 Table
(
[id] [int],
[field1] [decimal](18,4)
)
INSERT INTO #varTable1
VALUES
(1,20),
(1,NULL),
(1,NULL),
(1,NULL),
(2,NULL)
;with CTE as
(
SELECT *,row_number()over(order by id)rn FROM #varTable1
),
CTE1 as
(
select id, min([field1])Minfield from #varTable1
group by [id]
)
select vt.id,vt.field1,c.Minfield*rn from CTE VT
inner join CTE1 c on vt.id=c.id

Getiing multiple rows as output using case statement in sql

I have a table,
id category column1 column2 column3
1 1 val1a val1b val1c
2 2 val2a val2b val2c
3 3 val3a val3b val3c
from which I need to select columns based on multiple conditions something like below.
SELECT id, category, column1, column2, column3
FROM table
WHERE id = #id
AND category IN (
select case when (#input1='Yes' AND #input2='Yes') then (select category from table where category in ('1','2'))
when (#input1='Yes' AND #input2='No') then (select category from table where category ='1')
when (#input1='No' AND #input2='Yes') then (select category from table where category ='2')
else ''
end as category)
END
Input values #input1 and #input2 are grabbed from another table, need to select and output rows with category in ('1','2') according to above condition.
What I need -
if input1=Yes and input2=Yes output rows with category in ('1','2')
if input1=Yes and input2=No output rows with category in ('1')
if input1=No and input2=Yes output rows with category in ('2')
if input1=No and input2=No output rows with category in ('')
Does case statement output multiple values? Need help.
check out the code below, you don't need to use CASE WHEN, just use where condition combinations will do the trick.
create table [Test] ( id int, category nvarchar(10));
insert [Test] values(1,'1');
insert [Test] values(2,'2');
insert [Test] values(3,'1');
insert [Test] values(4,'2');
declare #input1 varchar(10) = 'Yes'
declare #input2 varchar(10) = 'No'
SELECT id, category
FROM [Test]
WHERE
(
( #input1 = 'Yes' and category ='1')
or
( #input2 = 'Yes' and category ='2')
)
If you wanted to use in, you could use:
where id = #id and
category in ( (case when #input1 = 'Yes' then 1 end),
(case when #input2 = 'Yes' then 2 end)
)
The default value for the case is NULL and that will fail any comparison.
Also, note that I removed the single quotes around '1' and '2'. These look like numbers, so I assume that category is a number. Quotes should only be used around string and date constants.
Maybe this:
SELECT id, category, column1, column2, column3
FROM table
WHERE id = #id
AND category IN
(
select category
from table
where
(
category = '1'
AND
#input1='Yes'
)
OR
(
category = '2'
AND
#input1='Yes'
)
)
or this:
SELECT id, category, column1, column2, column3
FROM table
WHERE id = #id
AND
(
(
#input1='Yes' AND #input2='Yes' AND category IN (select category from table where category in ('1','2')
)
OR
(
#input1='Yes' AND #input2='No' AND category IN (select category from table where category ='1')
)
OR
(
#input1='No' AND #input2='Yes' AND category IN (select category from table where category ='2')
)
)
I would suggest you to form a mapping table and leverage it in the SELECT query. It will result in simplified code and more clear approach.
;WITH CTE_MappingTable AS
(
SELECT *
FROM
(
values
('Yes','Yes',1),
('Yes','Yes',2),
('Yes','No',1),
('No','Yes',2)
) as t(input1,input2,category)
)
SELECT id, category, column1, column2, column3
FROM table as t
INNER JOIN CTE_MappingTable as c
ON c.Category = t.Category
WHERE id = #id AND c.input1 = #input1 AND c.input2 = #input2

How to return only numbers from query where column is nvarchar

I have a simple query that is returning records where "column2" > 0
Here is the data in the database
Column1 Column2
1 123456789
2 123456781
3 13-151-1513
4 alsdjf
5
6 000000000
Her is the query
select column1, replace(a.Payroll_id,'-','')
from table1
where isnumeric(column2) = 1
I'd like to return the following:
Column1 Column2
1 123456789
2 123456781
3 131511513
This mean, I won't select any records when the column is blank (or null), will not return a row if it's not an integer, and will drop out the '-', and would not show row 6 since it's all 0.
How can I do this?
I think you can use something like this :
USE tempdb
GO
CREATE TABLE #Temp
(
ID INT IDENTITY
,VALUE VARCHAR(30)
)
INSERT INTO #Temp (VALUE) VALUES ('1213213'), ('1213213'), ('121-32-13'), ('ASDFASF2123')
GO
WITH CteData
AS
(
SELECT REPLACE(VALUE,'-','') as Valor FROM #Temp
)
SELECT * FROM CteData WHERE (ISNUMERIC(Valor) = 1 AND valor not like '%[0-0]%')
DROP TABLE #Temp
then you can apply validations for empty, NULL,0 etc
If you are using SQL2012 or above you can also use TRY_PARSE that is more selective in its parsing. This function will return NULL if a record can't be converted. You could use it like this:
CREATE TABLE #temp
(
ID INT IDENTITY ,
VALUE VARCHAR(30)
)
INSERT INTO #temp
( VALUE )
VALUES ( '1213213' ),
( '1213213' ),
( '121-32-13' ),
( 'ASDFASF2123' ),
( '0000000' )
SELECT ParsedValue
FROM #temp
CROSS APPLY ( SELECT TRY_PARSE(
Value AS INT ) AS ParsedValue
) details
WHERE ParsedValue IS NOT NULL
AND ParsedValue>0

dynamic columns in Query Or view

Please Help me. How can i show dynamic columns in Query. I want a view.
Thanks in advance
My Out is like this.
select SectionID,
Column1, Column2, Column3
from
(
select S.SectionID,ColumnDataName, ColumnDescription,
row_number() over(partition by S.SectionID
order by SectionTableColumnID) seq
from dbo.SectionTableColumn vt
INNER JOIN dbo.Section S ON S.SectionID = vt.SectionID
) d
pivot
(
max(ColumnDescription)
for ColumnDataName in ( Column1, Column2, Column3)
) piv;
it is not possible to create a view with a dynamic number of columns. You need to specify all the values of ColumnDataName in order for this to work.
You need to pivot your result, here is an example how you can create your view:
CREATE TABLE
xxx(SectionID int, ColumnDescription varchar(10), ColumnDataName varchar(10))
INSERT xxx values(2, 'dgj', 'column1')
INSERT xxx values(2, 'ash', 'column2')
INSERT xxx values(8, 'lkhsdh', 'column2')
go
CREATE VIEW v_xxx as
SELECT SectionId, [column1],[column2],[column3]
FROM xxx
PIVOT
(min(ColumnDescription)
FOR ColumnDataName
in([column1],[column2],[column3])
)AS p
go
SELECT * FROM v_xxx
Result:
SectionId column1 column2 column3
2 dgj ash NULL
8 NULL lkhsdh NULL

Union temporary tables to a final temporary table

I have like 10 diff temporary tables created in SQL server, what I am looking to do is union them all to a final temporary table holding them all on one table. All the tables have only one row and look pretty much exactly like the two temp tables below.
Here is what I have so far this is an example of just two of the temp tables as their all exactly like this one then #final is the table I want to union the all to:
create table #lo
(
mnbr bigint
)
insert into #login (mnbr)
select distinct (_ID)
FROM [KDB].[am_LOGS].[dbo].[_LOG]
WHERE time >= '2012-7-26 9:00:00
Select count(*) as countreject
from #lo
create table #pffblo
(
mber_br
)
insert into #pffblo (mber_br)
select distinct (mber_br)
from individ ip with (nolock)
join memb mp with (nolock)
on( ip.i_id=mp.i_id and mp.p_type=101)
where ip.times >= '2012-9-26 11:00:00.000'
select count(*) as countaccept
create table #final
(
countreject bigint
, Countacceptbigint
.....
)
insert into #final (Countreject, Countaccept....more rows here...)
select Countreject, Countaccept, ...more rows selected from temp tables.
from #final
union
(select * from #lo)
union
(select * from #pffblo)
select *
from #final
drop table #lo
drop table #pffblo
drop table #final
if this the form to union the rows form those temp tables to this final one. Then is this correct way to show all those rows that were thus unioned. When I do this union I get message number of columns in union need to match number of columns selected in union
I think you're using a union the wrong way. A union is used when you have to datasets that are the same structure and you want to put them into one dataset.
e.g.:
CREATE TABLE #Table1
(
col1 BIGINT
)
CREATE TABLE #Table2
(
col1 BIGINT
)
--populate the temporary tables
CREATE TABLE #Final
(
col1 BIGINT
)
INSERT INTO #Final (col1)
SELECT *
FROM #Table1
UNION
SELECT *
FROM #Table2
drop table #table1
drop table #table2
drop table #Final
I think what you're trying to do is get 1 data set with the count of all your tables in it. Union won't do this.
The easiest way (although not very performant) would be to do select statements like the following:
CREATE TABLE #Table1
(
col1 BIGINT
)
CREATE TABLE #Table2
(
col1 BIGINT
)
--populate the temporary tables
CREATE TABLE #Final
(
col1 BIGINT,
col2 BIGINT
)
INSERT INTO #Final (col1, col2)
select (SELECT Count(*) FROM #Table1) as a, (SELECT Count(*) FROM #Table2) as b
select * From #Final
drop table #table1
drop table #table2
drop table #Final
It appears that you want to take the values from each of temp tables and then place then into a single row of data. This is basically a PIVOT, you can use something like this:
create table #final
(
countreject bigint
, Countaccept bigint
.....
)
insert into #final (Countreject, Countaccept....more rows here...)
select
from
(
select count(*) value, 'Countreject' col -- your UNION ALL's here
from #lo
union all
select count(*) value, 'countaccept' col
from #pffblo
) x
pivot
(
max(value)
for col in ([Countreject], [countaccept])
) p
Explanation:
You will create a subquery similar to this that will contain the COUNT for each of your individual temp table. There are two columns in the subquery, one column contains the count(*) from the table and the other column is the name of the alias:
select count(*) value, 'Countreject' col
from #lo
union all
select count(*) value, 'countaccept' col
from #pffblo
You then PIVOT these values to insert into your final temp table.
If you do not want to use PIVOT, then you can use a CASE statement with an aggregate function:
insert into #final (Countreject, Countaccept....more rows here...)
select max(case when col = 'Countreject' then value end) Countreject,
max(case when col = 'countaccept' then value end) countaccept
from
(
select count(*) value, 'Countreject' col -- your UNION ALL's here
from #lo
union all
select count(*) value, 'countaccept' col
from #pffblo
) x
Or you might be able to JOIN all of the temp tables similar to this, where you create a row_number() for the one record in the table and then you join the tables with the row_number():
insert into #final (Countreject, Countaccept....more rows here...)
select isnull(lo.Countreject, 0) Countreject,
isnull(pffblo.Countaccept, 0) Countaccept
from
(
select count(*) Countreject,
row_number() over(order by (SELECT 0)) rn
from #lo
) lo
left join
(
select count(*) Countaccept,
row_number() over(order by (SELECT 0)) rn
from #pffblo
) pffblo
on lo.rn = pffblo.rn
SELECT *
INTO #1
FROM TABLE2
UNION
SELECT *
FROM TABLE3
UNION
SELECT *
FROM TABLE4
If you would like to get count for each temporary table in the resulting table, you will need just to calculate it for each column in subquery:
INSERT INTO result (col1, col2,...
SELECT
(SELECT COUNT() FROM tbl1) col1
,(SELECT COUNT() FROM tbl2) col2
..