Select particular columns and insert in another table - sql-server

My tables are defined like below:
#TempData(ColmnA, ColumnB) -- Temp table.
EmployeeDSU(ColumnA, ColumnB, ColumnC, ColumnD, ColumnE)
#TempData is coming from .csv file and columns may change.
Now, what I want to do is:
If ColumnA, ColumnB exists in EmployeesDSU table, then the #TempData data should be inserted into EmployeesDSU table, and for all the remaining columns in EmployeesDSU table, NULL should be inserted. I should do this everything in Stored procedure.
Can anybody please suggest me how to do!

if object_id('tempdb..#TempData') is not null drop table #TempData;
select 1 ColumnA, 1 ColumnB into #TempData;
if not exists(
select
*
from
(
select
c.name
from
tempdb.sys.columns c
where
c.object_id = object_id('tempdb..#TempData')
) a
left join (
select
*
from
sys.columns c
where
c.object_id = object_id('dbo.EmployeeDSU')
) b on a.name = b.name
where
b.name is null
) begin
insert into dbo.EmployeeDSU(ColumnA, ColumnB)
select
t.ColumnA, t.ColumnB
from
#TempData t
;
end;

Related

Count columns of a result from with block?

I am exploring provided code. I have various CTEs, and I want to count the columns in each CTE? Or select the differences in columns per CTE?
The below code will grab the count from a table in the DB, but I'm not sure how to apply this to CTEs?
select count(*)
from INFORMATION_SCHEMA.columns
where TABLE_CATALOG = 'db_name'
and TABLE_NAME = 'table_name'
First Create CTE and then insert just one record into temp table , then query the sys.columns table to get the list of the columns in CTE
IF OBJECT_ID('tempdb.dbo.#temp', 'U') IS NOT NULL
DROP TABLE #temp;
go
With CTE1 as (select * from table_name)
select top 1 * into #temp from CTE1
SELECT count(*) FROM tempdb.sys.columns where object_id = object_id('tempdb..#temp')

Getting a Row Count and keeping the columns with no rows are returned

If I run something like this:
select [agent_name], [agent_department], count(*) as [row_count]
from [table_name]
where [agent_name] IS NOT NULL
group by [agent_name] [agent_department];
Nothing will come back if there are no records to return (i.e. the table is empty).
If I run this
select count(*) as [row_count]
from [table_name]
where [agent_name] IS NOT NULL
I will get a row_count of 0.
Is there a way I can run the first query, and, if there are no records, have it return row_count 0?
This might not be very beautiful, but it should bring back what you want:
I start with a tiny mockup:
DECLARE #mockup TABLE(agent_name varchar(100),agent_department varchar(100));
--The query will read your SELECT within a CTE.
WITH cte AS
(
select [agent_name], [agent_department], count(*) as [row_count]
from #mockup
where [agent_name] IS NOT NULL
group by [agent_name],[agent_department]
)
SELECT agent_name,agent_department,row_count FROM cte
UNION ALL SELECT NULL,NULL,0 WHERE (SELECT COUNT(*) FROM cte)=0;
The result
agent_name agent_department row_count
NULL NULL 0
You see, that the resultset is called as is, while there is a UNION ALL SELECT query, which will deliver only in cases, where the cte has no rows.
Now we insert some data to the table
INSERT INTO #mockup VALUES('blah','blub');
WITH cte AS
(
select [agent_name], [agent_department], count(*) as [row_count]
from #mockup
where [agent_name] IS NOT NULL
group by [agent_name],[agent_department]
)
SELECT agent_name,agent_department,row_count FROM cte
UNION ALL SELECT NULL,NULL,0 WHERE (SELECT COUNT(*) FROM cte)=0;
the new result is now
agent_name agent_department row_count
blah blub 1

How can I delete the duplicate rows while keeping the original record?

I have an one table as below a picture which indicates some duplicated rows.I can find the duplicated rows but I could not able to delete it because of there is no any unique ID that I can distinguish. There were lots of duplicated rows like that in same table I just screenshot a piece of that.
As a result,according to the below picture, how can I delete the duplicated rows but keep original ?
One solution you could consider is copying all unique records into a temporary table, thus removing the duplicates. You could then truncate the original table and re-populate it from the temporary table you've created. The code would be something like this:
SELECT DISTINCT * INTO #tempTable FROM MyTable
TRUNCATE TABLE MyTable;
INSERT INTO MyTable (LocationID, UnitID, CameraID ... IsActiveHours)
SELECT LocationID, UnitID, CameraID ... IsActiveHours FROM #tempTable;
This isn't always an option due to key constraints and amount of data, but useful in certain cases. Take it as you may.
You could use a cte and Row_Number() to accomplish this. If you are satisfied with the results, remove the final select and un-comment the delete statement
;with cte as (
Select *,RowNr=Row_Number() over (Partition By LocationId Order by Date_T)
From YourTable
)
Select * from cte Where RowNr>1
-- Delete From cte Where RowNr>1
You would be best adding an identity column to make things easier however this can be done without a TRUNCATE using the following:
--GET DUPLICATE ROWS INTO A TEMP TABLE (YOU MAY NOT NEED TO USE ALL THE COLUMNS TO IDENTIFY A DUPLICATE)
SELECT ROW_NUMBER() OVER (ORDER BY ColA) AS RowNo, ColA, ColB, ColC, COUNT(*) As [Count]
INTO #TEMP1
FROM test
GROUP BY ColA, ColB, ColC
HAVING COUNT(*) > 1
--LOOP THROUGH DUPLICATES
DECLARE #RowNo INT
DECLARE #Duplicates INT
SET #RowNo = 1
WHILE EXISTS(SELECT * FROM #TEMP1)
BEGIN
--GET A COUNT OF ADDITIONAL ROWS FOR THIS DUPLICATE
SET #Duplicates = (SELECT [Count] FROM #TEMP1 WHERE RowNo = #RowNo) - 1
--DELETE THE ROWS WE DONT NEED
DELETE TOP (#Duplicates) t1
FROM test t1
JOIN #TEMP1 t2 ON t1.ColA = t2.ColA AND t1.ColB = t2.ColB AND t1.ColC = t2.ColC
WHERE t2.RowNo = #RowNo
--REMOVE THE ROW FROM THE TEMP TABLE
DELETE FROM #TEMP1 WHERE RowNo = #RowNo
--INCREASE THE ROW NO TO MOVE TO THE NEXT ROW
SET #RowNo = #RowNo + 1
END
--DROP THE TEMP TABLE
DROP TABLE #TEMP1
This is the query that fix this issue.
WITH X AS (
SELECT ROW_NUMBER() OVER(PARTITION BY LocationId,date_t ORDER BY LocationId desc) as 'rownum',LocationId,
date_T AS T
FROM Counts
)
--SELECT * FROM X WHERE rownum >1
DELETE FROM X
WHERE rownum <> 1

String Replace column data with data from another table

I have two tables:
TableA:
ID Values
---------------
1 Q
2 B
3 TA
4 BS
TableB:
RawValue Value
------------------
[1][4] QBS
[2][1][3] BQTA
I need to generate TableB values with its given RawValues. each [X] in rawvalue is the ID coulmn of TableA and shoud be replace with its value .
[1][4] means that Value of TableA with has ID of 1 (Q) and Value of TableA with has ID of 4 (BS) then should equal to QBS.
can anyone suggest a way to do it?
this is what I have already tried:
update tableb set value=replace(rawvalue,'[' + (select id from tablea where id = cast(replace(replace(rawdata,'[',''),']','') as int)) + ']',
(select values from tablea where id = cast(replace(replace(rawdata,'[',''),']','') as int)))
By the way: this is still in test process and I can totally change tables, rowvalue format and replacement methods if anyone has a better idea.
declare #tableA table (id int, value varchar(50))
insert into #tableA (id, value)
select 1, 'Q' union all
select 2, 'B' union all
select 3, 'TA' union all
select 4, 'BS'
declare #tableB table (rawdata varchar(255), value varchar(255))
insert into #tableB (rawdata)
select '[1][4]' union all -- QBS
select '[2][1][3]' -- BQTA
update b
set value = (
select a.value + ''
from #tableA a
cross apply (select charindex ('[' + cast (a.id as varchar(50)) + ']', b.rawdata) as pos) p
where pos > 0
order by pos
for xml path('')
)
from #tableB b
select * from #tableB
P.S. I would recommend not to name field similar to reserved keywords (I mean Values).
Turn RawValue into XML, shred the XML to get one row for each value in RawValue and join to TableA to get the value.
Use the for xml path() trick to concatenate the values from TableA.
update TableB
set Value = (
select T.Value as '*'
from (
select row_number() over(order by T2.X) as SortOrder,
TableA.Value
from (select cast(replace(replace(TableB.RawValue, '[', '<x>'), ']', '</x>') as xml)) as T1(X)
cross apply T1.X.nodes('x') as T2(X)
inner join TableA
on TableA.ID = T2.X.value('text()[1]', 'int')
) as T
order by T.SortOrder
for xml path('')
)
SQL Fiddle

Is there a way to get the fields names of a table created in a function / stored procedure?

when I need the columns of an existing table I use the query:
SELECT c.[name]
FROM
(SELECT * from syscolumns) c
INNER JOIN
(SELECT [id] from sysobjects where name= 'tableName') o on c.[id]=o.[id]
I need the fields of a table that I create during runTime:
select
a.ID,
b.lName,
b.fName
into #T
from
a
inner join
b on a.id=b.id
.
select * from #T_columns
will result a table with 3 rows:
id
lName
fName
How can I do it?
Thanks
When you create a temp table, it will be in tempdb. You can look it up like this:
SELECT COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '#T|_%' ESCAPE '|'
If you do a SELECT * FROM INFORMATION_SCHEMA.TABLES in tempdb, you'll see the temp table name you use (#T) actually has a number of underscores appended to it followed by a unique identifier. So you won't find it it you just search where table_name = '#T'.
So that's why you have to use a LIKE as I've shown above. This will match on "#T_" followed by any other other characters.
Try this
SELECT sc.NAME
FROM
tempdb..SYSOBJECTS so JOIN
tempdb..SYSCOLUMNS sc ON sc.id = so.id
WHERE so.NAME LIKE '#T%'

Resources