Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
ashley.sql
Constraint Violating Yak Guru
299 Posts |
Posted - 2010-09-23 : 15:59:42
|
| I have a following table which needs to have comparison between today and yesterdays data.If customer deletes or adds items it will show up in 2 rows for both days as ORDER AMENDED. If order is not in yesterday it will show up as NEW ORDER ADDED. If its in yesterday data and not today it will show as ORDER SHIPPED.Thats what the script below does. Now I want to be able to do the following using a dynamic SQL. Say a new column called NUMBER_ITEMS and WEIGHT are added to #tempchanges will have to be made to this comparison.Well is there a way to make this DYNAMIC so that it does not matter columns are added or deleted it should compare by custid. CustID will always be there.create table #temp(custid INT,num_orders INT,Tot_Amount MONEY,Data_Date DATETIME)INSERT INTO #temp SELECT 11, 2, 250, '9/14/2010' UNION ALLSELECT 22, 3, 120, '9/14/2010' UNION ALLSELECT 55, 1, 1000, '9/14/2010' UNION ALLSELECT 44, 1, 500, '9/14/2010' UNION ALLSELECT 77, 15, 15000, '9/14/2010' UNION ALLSELECT 11, 3, 350, '9/15/2010' UNION ALLSELECT 22, 4, 100, '9/15/2010' UNION ALLSELECT 44, 1, 500, '9/15/2010' UNION ALLSELECT 77, 10, 10000, '9/15/2010' UNION ALLSELECT 33, 5, 140, '9/15/2010' DECLARE @previousdate DATETIME, @currentdate datetimeSET @previousdate = '9/14/2010'SET @currentdate = '9/15/2010'Select * into #previousdate from #temp where data_date = @previousdateSelect * into #currentdate from #temp where data_date = @currentdateSELECT 'NEW ORDER ADDED' AS [STATUS], * ,'NEW' AS STAMPFROM #currentdate cWHERE c.custid NOT IN (Select custid FROM #previousdate)UNION ALLSELECT 'ORDERS SHIPPED', * ,'SHIPPED'FROM #previousdate pWHERE p.custid NOT IN (SELECT custid FROM #currentdate)UNION ALL SELECT 'ORDER AMENDED', p.*,'PREVIOUS VALUE'FROM #previousdate pINNER JOIN #currentdate C ON c.custid = p.custidWHERE c.Data_Date <> p.Data_Date OR c.Tot_Amount <> c.Tot_Amount OR c.num_orders <> c.num_ordersUNION ALL SELECT 'ORDER AMENDED', c.*,'CURRENT VALUE'FROM #previousdate pINNER JOIN #currentdate C ON c.custid = p.custidWHERE c.Data_Date <> p.Data_Date OR c.Tot_Amount <> c.Tot_Amount OR c.num_orders <> c.num_ordersORDER BY custid, STATUS, Data_DateDROP TABLE #temp,#previousdate,#currentdate-----------------------------------------------------------------------------------------------Ashley Rhodes |
|
|
rohitvishwakarma
Posting Yak Master
232 Posts |
Posted - 2010-09-24 : 06:26:21
|
| DECLARE @objname nvarchar(776)SET @objname = 'Sales' -- Your Table NameDECLARE @objid intDECLARE @sysobj_type char(2)SELECT @objid = object_id, @sysobj_type = type FROM sys.all_objects WHERE object_id = object_id(@objname)SELECT name into #temp_table FROM sys.all_columns where object_id = @objid WHERE name NOT IN(custid ) -- Add columns which are going to be constant.Use WHILE LOOP on #temp_table to get the column list as string |
 |
|
|
rohitvishwakarma
Posting Yak Master
232 Posts |
Posted - 2010-09-24 : 10:19:55
|
Here is the complete query:DECLARE @objname nvarchar(776)SET @objname = '#temp' -- give the table name here DECLARE @objid intDECLARE @sysobj_type char(2)SELECT @objid = object_id, @sysobj_type = type from sys.all_objects where object_id = object_id(@objname)DECLARE @previousdate DATETIME, @currentdate datetimeDECLARE @union VARCHAR(15)DECLARE @sql_final VARCHAR(MAX)DECLARE @sql_fill_previous_table VARCHAR(1000)DECLARE @sql_fill_current_table VARCHAR(1000)DECLARE @sql_NEW_ORDER_ADDED VARCHAR(1000)DECLARE @sql_ORDERS_SHIPPED VARCHAR(1000)DECLARE @sql_ORDER_AMENDED_PREVIOUS VARCHAR(1000)DECLARE @sql_ORDER_AMENDED_CURRENT VARCHAR(1000)SET @union = 'UNION ALL' SET @previousdate = '9/14/2010'SET @currentdate = '9/15/2010' SET @sql_fill_previous_table = 'SELECT * INTO #previousdate FROM #temp WHERE data_date = ' + '''' + CAST(@previousdate AS VARCHAR(50)) + ''''SET @sql_fill_current_table = ' SELECT * INTO #currentdate FROM #temp WHERE data_date = ' + '''' + CAST(@currentdate AS VARCHAR(50)) +''''SET @sql_NEW_ORDER_ADDED = 'SELECT ''NEW ORDER ADDED'' AS [STATUS], * ,''NEW'' AS STAMPFROM #currentdate cWHERE c.custid NOT IN (SELECT custid FROM #previousdate)'SET @sql_ORDERS_SHIPPED = 'SELECT ''ORDERS SHIPPED'', * ,''SHIPPED''FROM#previousdate pWHERE p.custid NOT IN (SELECT custid FROM #currentdate) 'SET @sql_ORDER_AMENDED_PREVIOUS = 'SELECT ''ORDER AMENDED'', p.*,''PREVIOUS VALUE''FROM#previousdate pINNER JOIN #currentdate C ON c.custid = p.custidWHERE c.Data_Date <> p.Data_Date OR 'SET @sql_ORDER_AMENDED_CURRENT = 'SELECT ''ORDER AMENDED'', c.*,''CURRENT VALUE''FROM#previousdate pINNER JOIN #currentdate C ON c.custid = p.custidWHERE c.Data_Date <> p.Data_Date OR ' CREATE table #temp_table(id INT IDENTITY(1,1),Column_Names VARCHAR(150)) INSERT INTO #temp_table SELECT name FROM sys.all_columns WHERE object_id = @objid AND name NOT IN ('custid','Data_Date')DECLARE @count INTDECLARE @count_max INTDECLARE @or_part VARCHAR(200)SET @count = 1 SET @count_max = (SELECT MAX(id) FROM #temp_table)SET @or_part = ''WHILE (@count < @count_max)BEGIN DECLARE @column VARCHAR(150) SELECT @column = Column_Names FROM #temp_table WHERE id = @count SET @or_part = ' c.' + @column + ' <> ' + ' p.'+@column +' OR ' SET @sql_ORDER_AMENDED_PREVIOUS += @or_part SET @sql_ORDER_AMENDED_CURRENT += @or_part SET @count = @count + 1ENDSET @sql_final = @sql_fill_previous_table + @sql_fill_current_table + @sql_NEW_ORDER_ADDED + @union + @sql_ORDERS_SHIPPED + @union + @sql_ORDER_AMENDED_PREVIOUS + @union + @sql_ORDER_AMENDED_CURRENT PRINT @sql_final-- EXEC(@sql_final)Thanks Rohit |
 |
|
|
ashley.sql
Constraint Violating Yak Guru
299 Posts |
Posted - 2010-09-24 : 11:44:58
|
| You cannot hard code dynamic SQL it has to be created using information schema.-----------------------------------------------------------------------------------------------Ashley Rhodes |
 |
|
|
rohitvishwakarma
Posting Yak Master
232 Posts |
Posted - 2010-09-24 : 12:08:42
|
quote: Originally posted by ashley.sql You cannot hard code dynamic SQL it has to be created using information schema.-----------------------------------------------------------------------------------------------Ashley Rhodes
It is being created using Schema using the part:CREATE table #temp_table(id INT IDENTITY(1,1),Column_Names VARCHAR(150)) INSERT INTO #temp_table SELECT name FROM sys.all_columns WHERE object_id = @objid AND name NOT IN ('custid','Data_Date') -- this will get the columns other than those present in 'IN',you may add other columns which are fixed but not mentioned in the post.and WHILE loop. This WHILE loop adds the condition inh the WHERE Claues for the last two SELECT Statements using the columns retrieved above. so in future if any columns gets added to your table you don't need to modify the queryI have hardcoded the parts which are going to be remain same i.e for date and customer_id columns & SELECT statements,only the WHERE cluase needs to be dynamic.ThanksRohit |
 |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2010-09-24 : 14:24:07
|
The following uses non-dynamic SQL, gives the same results as your original query, and will work no matter how many columns are added:;WITH pre(custid,data_date) AS (SELECT custid,data_date FROM #temp WHERE data_date=@previousdate), cur(custid,data_date) AS (SELECT custid,data_date FROM #temp WHERE data_date=@currentdate), shipped(custid) AS (SELECT custid FROM pre EXCEPT SELECT custid FROM cur), added(custid) AS (SELECT custid FROM cur EXCEPT SELECT custid FROM pre)SELECT 'ORDERS SHIPPED' Status, a.*, 'SHIPPED' STAMP FROM #temp a INNER JOIN shipped b ON a.custid=b.custidUNIONSELECT 'NEW ORDER ADDED', a.*, 'NEW' FROM #temp a INNER JOIN added b ON a.custid=b.custidUNIONSELECT 'ORDER AMENDED', a.*, 'PREVIOUS VALUE' FROM #temp a INNER JOIN pre b ON a.custid=b.custid AND a.data_date=b.data_dateWHERE a.custid NOT IN(SELECT custid FROM shipped)UNIONSELECT 'ORDER AMENDED', a.*, 'CURRENT VALUE' FROM #temp a INNER JOIN cur b ON a.custid=b.custid AND a.data_date=b.data_dateWHERE a.custid NOT IN(SELECT custid FROM added)ORDER BY custid, STATUS, Data_Date This does not require column comparisons since it assumes anything not shipped nor added is amended. I noticed CustID 44 in your sample data has not changed (except for Data_date), is that considered a dupe? If not then this will satisfy your requirements. |
 |
|
|
|
|
|
|
|