How to interrogate multiple tables with different structure? - sql

I am using Sql-Server 2016 in a C# application.
Let's say I have two tables:
CREATE TABLE Table_A
(
UserID NVARCHAR2(15),
FullName NVARCHAR2(25),
Available NUMBER(1),
MachineID NVARCHAR2(20),
myDate date
);
and
CREATE TABLE Table_B
(
UserID NVARCHAR2(15),
FullName NVARCHAR2(25),
Team NVARCHAR2(15),
MachineID NVARCHAR2(20),
Stuff NUMBER(2)
);
I want to perform a global select so that I will get as result data from both tables, somehow concatenated and of course, when a column does not exist in one of the tables, that column to be automatically populated with NULL, and if a column exists on both tables the results must be merged in a single column.
The first solution that pops-up is a UNION with NULL aliases for the missing columns, sure. The problem is that at runtime I will not be able to know in advance which tables are interrogated so that I could anticipate the column names. I need a more general solution.
The expected result from the two tables must look like this:
user_Table_A; fullName_Table_A; 1; machineID_Table_A; 12-JUN-18; NULL; 10;
user_Table_B; fullName_Table_B; NULL; machineID_Table_B; NULL; team_Table_B; 20;
The data for the two tables is inserted with the following commands:
INSERT INTO Table_A VALUES ('user_Table_A', 'fullName_Table_A', 1, 'machineID_Table_A', TO_DATE('12-06-2018', 'DD-MM-YYYY'));
INSERT INTO Table_B VALUES ('user_Table_B', 'fullName_Table_B', 'team_Table_B', 'machineID_Table_B', 20);

You can do something like this. I havent have time to completely tweak it, so there can be something the order of the columns. But perhaps it can get you started:
You also write that you use Oracle - Im not sure what you wanted, but this is in pure sql-server version.
SQL:
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
/*Then it exists*/
DROP TABLE #temp;
GO
DECLARE #SQLList nvarchar(max)
DECLARE #SQLList2 nvarchar(max)
DECLARE #SQL nvarchar(max)
with table_a as (
select column_name as Table_aColumnName,ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'table_a'
)
,
table_b as (
select column_name as Table_bColumnName,ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'table_b'
)
,preresult as (
select case when Table_aColumnName IS null then 'NULL as ' + Table_bColumnName else Table_aColumnName end as Table_a_ColumnName,case when Table_bColumnName IS null then 'NULL as ' +Table_aColumnName else Table_bColumnName end as Table_b_ColumnName
,a.ORDINAL_POSITION,b.ORDINAL_POSITION as Table_b_Ordinal from table_a a full join Table_B b on a.Table_aColumnName = b.Table_bColumnName
)
select * into #temp from preresult
SET #SQLList = (
select distinct display = STUFF((select ','+table_a_columnName from #temp b order by table_b_ordinal FOR XML PATH('')),1,1,'') from #temp a
)
SET #SQLList2 = (
select distinct display = STUFF((select ','+table_b_columnName from #temp b order by Table_b_Ordinal FOR XML PATH('')),1,1,'') from #temp a
)
SET #SQL = 'select ' +#SQLList +' from dbo.Table_a union all select ' + #SQLList2 + ' from dbo.table_b'
exec(#SQL)
Result:

Related

how to get a select count(x) from a query of table names

I have a query the brings back a list of tables and the counts of those tables.
select *
from error
with a result of
tablename | errorcnt
----------+---------
table1 | 5
table2 | 256
and so on.
I need to do a join so I can get another count from each table as to the records that have been corrected example
select count(fixed)
from table1
so my new result would be
tablename | errorcnt | fixed
----------+----------+------
table1 | 5 | 3
table2 | 256 | 239
and so on.
Without doing a cursor how could I do? I guess a sub query using 'tablename'.
The comment you made:
This is how i populate my errortable SELECT T.name TableName,i.Rows
NumberOfRows FROM sys.tables T JOIN sys.sysindexes I ON T.OBJECT_ID =
I.ID WHERE indid IN (0,1) ORDER BY i.Rows DESC,T.name
Means you are looking for tables, and their respective indexes, for tables that are either a heap (i.e. has no index) or have a clustered index. I'm not sure why this would classify as an "error". I'd expect you to want to look for only heaps. i.e. on where indid = 0. Regardless, I suppose the "fixed" would be to return tables that, for example, didn't have a clustered index which now does. In that case I don't understand the schema and think you have asked a XY Question
With that being said,based off the other comments, you could use derived tables and join on the literal values of error.tablename to prevent the use of a cursor.
select
error.tablename
,error.errorcnt
,fixed = coalesce(t1.ct, t2.ct) --add in for each join.
from
error
left join (select count(fixed) as ct from table1 where fixed = 'Y') as t1 on error.tablename = 'table1'
left join (select count(fixed) as ct from table2 where fixed = 'Y') as t2 on error.tablename = 'table2'
--continue the joins for all values in error.tablename
A cursor would be less code, and dynamic, but you asked for a way without a cursor.
you can use temp table and while loop avoid cursor
DECLARE
#SQLQuery NVARCHAR(100),
#Tablename VARCHAR(100)
CREATE TABLE
#error
(
tablename VARCHAR(100),
errorcnt INT
)
CREATE TABLE
#Table1
(
fixed INT
)
CREATE TABLE
#Table2
(
fixed INT
)
CREATE TABLE
#Temp_fixed
(
fixed INT
)
INSERT INTO
#error
VALUES
(
'#Table1',
5
),
(
'#Table2',
256
)
INSERT INTO
#Table1
VALUES
(
3
)
INSERT INTO
#Table2
VALUES
(
239
)
SELECT
tablename,
errorcnt,
-1 AS fixed
INTO
#Temp_error
FROM
#error
WHILE EXISTS(SELECT TOP 1 1 FROM #Temp_error WHERE fixed = -1)
BEGIN
SET
#Tablename = (SELECT TOP 1 tablename FROM #Temp_error WHERE fixed = -1)
SET
-- #SQLQuery = 'SELECT COUNT(fixed) FROM ' + #Tablename
#SQLQuery = 'SELECT SUM(fixed) FROM ' + #Tablename
INSERT INTO
#Temp_fixed
(
fixed
)
EXECUTE
sp_executesql
#SQLQuery
UPDATE
#Temp_error
SET
fixed = ISNULL((SELECT TOP 1 fixed FROM #Temp_fixed), 0)
WHERE
tablename = #Tablename
TRUNCATE TABLE #Temp_fixed
END
SELECT
tablename,
errorcnt,
fixed
FROM
#Temp_error
DROP TABLE #error
DROP TABLE #Table1
DROP TABLE #Table2
DROP TABLE #Temp_error
DROP TABLE #Temp_fixed

SQL Loop through tables and columns to find which columns are NOT empty

I created a temp table #test containing 3 fields: ColumnName, TableName, and Id.
I would like to see which rows in the #test table (columns in their respective tables) are not empty? I.e., for every column name that i have in the ColumnName field, and for the corresponding table found in the TableName field, i would like to see whether the column is empty or not. Tried some things (see below) but didn't get anywhere. Help, please.
declare #LoopCounter INT = 1, #maxloopcounter int, #test varchar(100),
#test2 varchar(100), #check int
set #maxloopcounter = (select count(TableName) from #test)
while #LoopCounter <= #maxloopcounter
begin
DECLARE #PropIDs TABLE (tablename varchar(max), id int )
Insert into #PropIDs (tablename, id)
SELECT [tableName], id FROM #test
where id = #LoopCounter
set #test2 = (select columnname from #test where id = #LoopCounter)
declare #sss varchar(max)
set #sss = (select tablename from #PropIDs where id = #LoopCounter)
set #check = (select count(#test2)
from (select tablename
from #PropIDs
where id = #LoopCounter) A
)
print #test2
print #sss
print #check
set #LoopCounter = #LoopCounter + 1
end
In order to use variables as column names and table names in your #Check= query, you will need to use Dynamic SQL.
There is most likely a better way to do this but I cant think of one off hand. Here is what I would do.
Use the select and declare a cursor rather than a while loop as you have it. That way you dont have to count on sequential id's. The cursor would fetch fields columnname, id and tablename
In the loop build a dynamic sql statement
Set #Sql = 'Select Count(*) Cnt Into #Temp2 From ' + TableName + ' Where ' + #columnname + ' Is not null And ' + #columnname <> '''''
Exec(#Sql)
Then check #Temp2 for a value greater than 0 and if this is what you desire you can use the #id that was fetched to update your #Temp table. Putting the result into a scalar variable rather than a temp table would be preferred but cant remember the best way to do that and using a temp table allows you to use an update join so it would well in my opinion.
https://www.mssqltips.com/sqlservertip/1599/sql-server-cursor-example/
http://www.sommarskog.se/dynamic_sql.html
Found a way to extract all non-empty tables from the schema, then just joined with the initial temp table that I had created.
select A.tablename, B.[row_count]
from (select * from #test) A
left join
(SELECT r.table_name, r.row_count, r.[object_id]
FROM sys.tables t
INNER JOIN (
SELECT OBJECT_NAME(s.[object_id]) table_name, SUM(s.row_count) row_count, s.[object_id]
FROM sys.dm_db_partition_stats s
WHERE s.index_id in (0,1)
GROUP BY s.[object_id]
) r on t.[object_id] = r.[object_id]
WHERE r.row_count > 0 ) B
on A.[TableName] = B.[table_name]
WHERE ROW_COUNT > 0
order by b.row_count desc
How about this one - bitmask computed column checks for NULLability. Value in the bitmask tells you if a column is NULL or not. Counting base 2.
CREATE TABLE FindNullComputedMask
(ID int
,val int
,valstr varchar(3)
,NotEmpty as
CASE WHEN ID IS NULL THEN 0 ELSE 1 END
|
CASE WHEN val IS NULL THEN 0 ELSE 2 END
|
CASE WHEN valstr IS NULL THEN 0 ELSE 4 END
)
INSERT FindNullComputedMask
SELECT 1,1,NULL
INSERT FindNullComputedMask
SELECT NULL,2,NULL
INSERT FindNullComputedMask
SELECT 2,NULL, NULL
INSERT FindNullComputedMask
SELECT 3,3,3
SELECT *
FROM FindNullComputedMask

SQL copying record with out specifying column list; ignoring Identity

I'm trying to copy a record from TableA back to TableA, but using a new Identity.
I don't want to specify column list as I have over 100 columns, and there may be more in the future. Id like a chunk of code that can run when/if things change.
After looking similar questions, I have attempted this code
SELECT * INTO #tmp FROM TableA WHERE Id = 1;
ALTER TABLE #tmp DROP COLUMN Id;
INSERT INTO TableA SELECT * FROM #tmp;
Drop Table #tmp;
I am however still getting this error
An explicit value for the identity column in table 'dbo.TableA' can only be specified when a column list is used and IDENTITY_INSERT is ON.
Running a Select * FROM #tmp gives me what I would expect. A single record with all my Columns with the exception of the Id column.
Any Ideas?
Thanks!
EDIT
Here is a pictures of the properties of the Id Column
Use Dynamic SQL: get your list of columns (except ID), build an insert statement using that list, and then call exec on it:
SELECT *
INTO #tmp
FROM TableA
WHERE Id = 1;
ALTER TABLE #tmp DROP COLUMN id;
DECLARE #cols varchar(max);
SELECT
#cols = COALESCE(#cols + ',', '') + COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TableA' AND COLUMN_NAME <> 'id'
--select #cols -- display column list for debugging
DECLARE #sqltxt varchar(max) = 'INSERT INTO TableA (' + #cols + ') SELECT * FROM #tmp';
--SELECT #sqltxt -- display the statement for debugging
exec (#sqltxt)
DROP TABLE #tmp
Try This
Step 1 :
INSERT INTO Employee1(FirstName,LastName,ManagerID,Salary)
SELECT FirstName,LastName,ManagerID,Salary
FROM Employee1
WHERE EmployeeID=X -- Your Emplyee ID
Step 2:
DELETE FROM Employee1 WHERE EmployeeID=X

Create a view based on column metadata

Let's assume two tables:
TableA holds various data measurements from a variety of stations.
TableB holds metadata, about the columns used in TableA.
TableA has:
stationID int not null, pk
entryDate datetime not null, pk
waterTemp float null,
waterLevel float null ...etc
TableB has:
id int not null, pk, autoincrement
colname varchar(50),
unit varchar(50) ....etc
So for example, one line of data from tableA reads:
1 | 2013-01-01 00:00 | 2.4 | 3.5
two lines from tableB read:
1| waterTemp | celcius
2| waterLevel | meters
This is a simplified example. In truth, tableA might hold close to 20 different data columns, and table b has close to 10 metadata columns.
I am trying to design a view which will output the results like this:
StationID | entryDate | water temperature | water level |
1 | 2013-01-01 00:00 | 2.4 celcius | 3.5 meters |
So two questions:
Other than specifying subselects from TableB (..."where
colname='XXX'") for each column, which seems horribly insufficient
(not to mention...manual :P ), is there a way to get the result I
mentioned earlier with automatic match on colname?
I have a hunch
that this might be bad design on the database. Is it so? If yes,
what would be a more optimal design? (Bear in mind the complexity of
the data structure I mentioned earlier)
dynamic SQL with PIVOT is the answer. though it is dirty in terms of debugging or say for some new developer to understand the code but it will give you the result you expected.
check the below query.
in this we need to prepare two things dynamically. one is list columns in the result set and second is list of values will appear in PIVOT query. notice in the result i do not have NULL values for Column3, Column5 and Column6.
SET NOCOUNT ON
IF OBJECT_ID('TableA','u') IS NOT NULL
DROP TABLE TableA
GO
CREATE TABLE TableA
(
stationID int not null IDENTITY (1,1)
,entryDate datetime not null
,waterTemp float null
,waterLevel float NULL
,Column3 INT NULL
,Column4 BIGINT NULL
,Column5 FLOAT NULL
,Column6 FLOAT NULL
)
GO
IF OBJECT_ID('TableB','u') IS NOT NULL
DROP TABLE TableB
GO
CREATE TABLE TableB
(
id int not null IDENTITY(1,1)
,colname varchar(50) NOT NULL
,unit varchar(50) NOT NULL
)
INSERT INTO TableA( entryDate ,waterTemp ,waterLevel,Column4)
SELECT '2013-01-01',2.4,3.5,101
INSERT INTO TableB( colname, unit )
SELECT 'WaterTemp','celcius'
UNION ALL SELECT 'waterLevel','meters'
UNION ALL SELECT 'Column3','unit3'
UNION ALL SELECT 'Column4','unit4'
UNION ALL SELECT 'Column5','unit5'
UNION ALL SELECT 'Column6','unit6'
DECLARE #pvtInColumnList NVARCHAR(4000)=''
,#SelectColumnist NVARCHAR(4000)=''
, #SQL nvarchar(MAX)=''
----getting the list of Columnnames will be used in PIVOT query list
SELECT #pvtInColumnList = CASE WHEN #pvtInColumnList=N'' THEN N'' ELSE #pvtInColumnList + N',' END
+ N'['+ colname + N']'
FROM TableB
--PRINT #pvtInColumnList
----lt and rt are table aliases used in subsequent join.
SELECT #SelectColumnist= CASE WHEN #SelectColumnist = N'' THEN N'' ELSE #SelectColumnist + N',' END
+ N'CAST(lt.'+sc.name + N' AS Nvarchar(MAX)) + SPACE(2) + rt.' + sc.name + N' AS ' + sc.name
FROM sys.objects so
JOIN sys.columns sc
ON so.object_id=sc.object_id AND so.name='TableA' AND so.type='u'
JOIN TableB tbl
ON tbl.colname=sc.name
JOIN sys.types st
ON st.system_type_id=sc.system_type_id
ORDER BY sc.name
IF #SelectColumnist <> '' SET #SelectColumnist = N','+#SelectColumnist
--PRINT #SelectColumnist
----preparing the final SQL to be executed
SELECT #SQL = N'
SELECT
--this is a fixed column list
lt.stationID
,lt.entryDate
'
--dynamic column list
+ #SelectColumnist +N'
FROM TableA lt,
(
SELECT * FROM
(
SELECT colname,unit
FROM TableB
)p
PIVOT
( MAX(p.unit) FOR p.colname IN ( '+ #pvtInColumnList +N' ) )q
)rt
'
PRINT #SQL
EXECUTE sp_executesql #SQL
here is the result
ANSWER to your Second Question.
the design above is not even giving performance nor flexibility. if user wants to add new Metadata (Column and Unit) that can not be done w/o changing table definition of TableA.
if we are OK with writing Dynamic SQL to give user Flexibility we can redesign the TableA as below. there is nothing to change in TableB. I would convert it in to Key-value pair table. notice that StationID is not any more IDENTITY. instead for given StationID there will be N number of row where N is the number of column supplying the Values for that StationID. with this design, tomorrow if user adds new Column and Unit in TableB it will add just new Row in TableA. no table definition change required.
SET NOCOUNT ON
IF OBJECT_ID('TableA_New','u') IS NOT NULL
DROP TABLE TableA_New
GO
CREATE TABLE TableA_New
(
rowID INT NOT NULL IDENTITY (1,1)
,stationID int not null
,entryDate datetime not null
,ColumnID INT
,Columnvalue NVARCHAR(MAX)
)
GO
IF OBJECT_ID('TableB_New','u') IS NOT NULL
DROP TABLE TableB_New
GO
CREATE TABLE TableB_New
(
id int not null IDENTITY(1,1)
,colname varchar(50) NOT NULL
,unit varchar(50) NOT NULL
)
GO
INSERT INTO TableB_New(colname,unit)
SELECT 'WaterTemp','celcius'
UNION ALL SELECT 'waterLevel','meters'
UNION ALL SELECT 'Column3','unit3'
UNION ALL SELECT 'Column4','unit4'
UNION ALL SELECT 'Column5','unit5'
UNION ALL SELECT 'Column6','unit6'
INSERT INTO TableA_New (stationID,entrydate,ColumnID,Columnvalue)
SELECT 1,'2013-01-01',1,2.4
UNION ALL SELECT 1,'2013-01-01',2,3.5
UNION ALL SELECT 1,'2013-01-01',4,101
UNION ALL SELECT 2,'2012-01-01',1,3.6
UNION ALL SELECT 2,'2012-01-01',2,9.9
UNION ALL SELECT 2,'2012-01-01',4,104
SELECT * FROM TableA_New
SELECT * FROM TableB_New
SELECT *
FROM
(
SELECT lt.stationID,lt.entryDate,rt.Colname,lt.Columnvalue + SPACE(3) + rt.Unit AS ColValue
FROM TableA_New lt
JOIN TableB_new rt
ON lt.ColumnID=rt.ID
)t1
PIVOT
(MAX(ColValue) FOR Colname IN ([WaterTemp],[waterLevel],[Column1],[Column2],[Column4],[Column5],[Column6]))pvt
see the result below.
I would design this database like the following:
A table MEASUREMENT_DATAPOINT that contains the measured data points. It would have the columns ID, measurement_id, value, unit, name.
One entry would be 1, 1, 2.4, 'celcius', 'water temperature'.
A table MEASUREMENTS that contains the data of the measurement itself. Columns: ID, station_ID, entry_date.
You might want to look into the MS-SQL function called PIVOT/UNPIVOT
http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
you can take column names and have them in rows or vice versa using this command.
Once you have the column name in the column itself you can join that column from tableA to tableB. Then unpivot to get your data back the way you want it. (caveat I may be swapping the use of pivot and unpivot :))
Word to the wise though, if you are working with large tables, pivot is not the fastest of operations.
I think you would have to flip it to a row per metric. Looking at your design above:
1 | 2013-01-01 00:00 | 2.4 | 3.5
How do I know what row in table b that applies to?
I would try something like this:
Table B:
Metric_Key | Metric
1 | WaterLevel in Meters
2 | Temp in Celcius
...
Table A:
StationID | entrydate | Metric_Key | Value
1 2013-01-01 00:00 1 2.4

Deleting duplicate record from table - SQL query

I need to delete duplicate rows only from the table, like I have 3 duplicate rows in the table, my query will delete 2 rows from 3 duplicated rows.
How can I get this? Please help me.
Please try the below query, it will definitely meet your objective
SET ROWCOUNT 1
DELETE test
FROM test a
WHERE (SELECT COUNT(*) FROM test b WHERE b.name = a.name) > 1
WHILE ##rowcount > 0
DELETE test
FROM test a
WHERE (SELECT COUNT(*) FROM test b WHERE b.name = a.name) > 1
SET ROWCOUNT 0
where test is your table name
This works in SQL Server although it isn't a single statement:
Declare #cnt int;
Select #cnt=COUNT(*) From DupTable Where (Col1=1); -- Assumes you are trying to delete the duplicates where some condition (e.g. Col1=1) is true.
Delete Top (#cnt-1) From DupTable
It also doesn't require any extra assumptions (like the existance of another column that makes each row unique). After all, Santanu did say that the rows were duplicates and not just the one column.
However, the right answer, in my view, is to get a real table structure. That is, add an IDENTITY column to this table so that you can use a single SQL command to do your work. Like this:
ALTER TABLE dbo.DupTable ADD
IDCol int NOT NULL IDENTITY (1, 1)
GO
Then the delete is trivial:
DELETE FROM DupTable WHERE IDCol NOT IN
(SELECT MAX(IDCol) FROM DupTable GROUP BY Col1, Col2, Col3)
DELETE FROM Table t1, Table t2 WHERE t1.colDup = t2.colDup AND t1.date < t2.date
Will delete every duplicate row from Table (on column colDup) except the oldest (i.e. lowset date).
DELETE FROM `mytbl`
INNER JOIN (
SELECT 1 FROM `mytbl`
GROUP BY `duplicated_column` HAVING COUNT(*)=2
) USING(`id`)
Edit:
My bad, the above query won't work.
Assuming table structure:
id int auto_increment
num int # <-- this is the column with duplicated values
The following query would work in MySQL (i checked):
DELETE `mytbl` FROM `mytbl`
INNER JOIN
(
SELECT `num` FROM `mytbl`
GROUP BY `num` HAVING COUNT(*)=2
) AS `tmp` USING (`num`)
The query would delete the rows that have 2 (not more or else) duplicated values in the num column.
Edit (again):
I suggest to add a key on the num column.
Edit(#3):
In case that the author wanted to delete the duplicated rows, the following should work for MySQL (it worked for me):
DELETE `delete_duplicated_rows` FROM `delete_duplicated_rows`
NATURAL JOIN (
SELECT *
FROM `delete_duplicated_rows`
GROUP BY `num1` HAVING COUNT(*)=2
) AS `der`
While assuming table structure is:
CREATE TABLE `delete_duplicated_rows` (
`num1` tinyint(4) DEFAULT NOT NULL,
`num2` tinyint(4) DEFAULT NOT NULL
) ENGINE=MyISAM;
If you have the id's of the rows you want to delete then...
DELETE FROM table WHERE id IN (1, 4, 7, [id numbers to delete...])
I think each table has unique identifier.
So if it exists then you can write following query:
Delete Table1 from Table1 t1 where 2 >= (select count(id) from Table1 where dupColumn = t1.dupColumn) and
t1.id not in (select max (id) from Table1 where dupColumn = t1.dupColumn)
OOps. It seems it is possible to use second filter only
Delete Table1 from Table1 t1 where
t1.id not in (select max (id) from Table1 where dupColumn = t1.dupColumn)
-- Just to demonstrates Marks example
.
-- START === 1.0.dbo..DuplicatesTable.TableCreate.sql
/****** Object: Table [dbo].[DuplicatesTable]
Script Date: 03/29/2010 21:24:02 ******/
IF EXISTS (SELECT * FROM sys.objects
WHERE
object_id = OBJECT_ID(N'[dbo].[DuplicatesTable]')
AND type in (N'U'))
DROP TABLE [dbo].[DuplicatesTable]
GO
/****** Object: Table [dbo].[DuplicatesTable]
Script Date: 03/29/2010 21:24:02 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[DuplicatesTable](
[ColA] [varchar](10) NOT NULL, -- the name of the DuplicatesTable
[ColB] [varchar](10) NULL, -- the description of the e DuplicatesTable
)
/*
<doc>
Models a DuplicatesTable for
</doc>
*/
GO
--============================================================ DuplicatesTable START
declare #ScriptFileName varchar(2000)
SELECT #ScriptFileName = '$(ScriptFileName)'
SELECT #ScriptFileName + ' --- DuplicatesTable START ========================================='
declare #TableName varchar(200)
select #TableName = 'DuplicatesTable'
SELECT 'SELECT name from sys.tables where name =''' + #TableName + ''''
SELECT name from sys.tables
where name = #TableName
DECLARE #TableCount INT
SELECT #TableCount = COUNT(name ) from sys.tables
where name =#TableName
if #TableCount=1
SELECT ' DuplicatesTable PASSED. The Table ' + #TableName + ' EXISTS '
ELSE
SELECT ' DuplicatesTable FAILED. The Table ' + #TableName + ' DOES NOT EXIST '
SELECT #ScriptFileName + ' --- DuplicatesTable END ========================================='
--============================================================ DuplicatesTable END
GO
-- END === 1.0.dbo..DuplicatesTable.TableCreate.sql
.
-- START === 1.1..dbo..DuplicatesTable.TableInsert.sql
BEGIN TRANSACTION;
INSERT INTO [dbo].[DuplicatesTable]([ColA], [ColB])
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA', N'ColB' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1' UNION ALL
SELECT N'ColA1', N'ColB1'
COMMIT;
RAISERROR (N'[dbo].[DuplicatesTable]: Insert Batch: 1.....Done!', 10, 1) WITH NOWAIT;
GO
-- END === 1.1..dbo..DuplicatesTable.TableInsert.sql
.
-- START === 2.0.RemoveDuplicates.Script.sql
ALTER TABLE dbo.DuplicatesTable ADD
DuplicatesTableId int NOT NULL IDENTITY (1, 1)
GO
-- Then the delete is trivial:
DELETE FROM dbo.DuplicatesTable WHERE DuplicatesTableId NOT IN
(SELECT MAX(DuplicatesTableId) FROM dbo.DuplicatesTable GROUP BY ColA , ColB)
Select * from DuplicatesTable ;
-- END === 2.0.RemoveDuplicates.Script.sql