Why does GETDATE keep getting called in MERGE statement? - tsql

I have a stored procedure that has a datetime var that gets set with GETDATE at the beginning of the proc and then calls a MERGE statement.
what happens is that NOT one date get's stamped but the date periodically CHANGES. This is a long running process.
Is there a way to get ONE date and stamp that on all records?
create proc MyProc as
declare #insertdate datetime
set #insertdate = getdate()
merge dbo.something as target
using (select col1,col2 from dbo.another) as source
on (target.col1 = source.col1 and target.col2 = source.col2)
when not matched by target
insert (col1, col2, insertdate) values (source.col1, souce.col2, #insertdate);

Related

PostgreSQL transforming the entire column value in a table

I have been trying to change all the values in a column. When I do it turns out to take my table and drop all the rows that match my criteria in the where clause.
Example
|_Month_|_Cost_|_Title_|
|___2___|_15.99|_hello_|
|___2___|_32.87|_John__|
|___2___|_32.87|_Neat__|
|___3___|_32.87|_Kelps_|
|___4___|_32.87|_Gulp__|
|___5___|_32.87|_Tried_|
I run this Query
UPDATE tableName SET Month = 'FEB' WHERE Month = 2;
The Change:
|_Month_|_Cost_|_Title_|
|__FEB__|_32.87|_Neat__|
|___3___|_32.87|_Kelps_|
|___4___|_32.87|_Gulp__|
|___5___|_32.87|_Tried_|
What I need:
|_Month_|_Cost_|_Title_|
|__FEB__|_15.99|_hello_|
|__FEB__|_32.87|_John__|
|__FEB__|_32.87|_Neat__|
|___3___|_32.87|_Kelps_|
|___4___|_32.87|_Gulp__|
|___5___|_32.87|_Tried_|
Where am I going wrong?
I have also tried to get the date changed from a timestamp with
SELECT TO_DATE(payment_timestamp, 'Mon") payment_month
from tablename;
but PostgreSQL doesn't recognize the TO_DATE()?? Can someone tell me why?

Can I do this calculation in a merge statement?

I am trying to do a calculation during a merge and it is not working. Is it even possible to this during a merge update? Or am I just missing something
I am using SQL Server for Azure 2018. I can verify that non calculations are being updated into table during merge. I have no issues with the insert
MERGE table1 AS s
USING (
SELECT #OId AS oID, #Partno AS partno, #PreviousTotal AS PreviousTotal,
#YearTotal AS YearTotal) AS source
ON s.oId = source.oId AND s.partno = source.partno
WHEN MATCHED THEN
UPDATE SET
UpdatedTotal = (#YearTotal + s.YearTotal) - #PreviousTotal,
PreviousTotal = source.PreviousTotal,
ReportDate = GetDate()
WHEN NOT MATCHED THEN
INSERT (...)
VALUES (...)
I just need to do the calculation before I update the record

SAS: Coding a dummy variable for a value of a variable by group within group

I have a dataset of CASE_ID (x y and z), a set of multiple dates (including duplicate dates) for each CASE_ID, and a variable VAR. I would like to create a dummy variable DUMMYVAR by group within a group whereby if VAR="C" for CASE_ID x on some specific date, then DUMMYVAR=1 for all observations corresponding to CASE_ID x on with that date.
I believe that a Classic 2XDOW would be the key here but this is my third week using SAS and having difficulty getting this by two BY groups here.
I have referenced and attempted to write a variation of Haikuo's code here:
PROC SORT have;
by CASE_ID DATE;
RUN;
data want;
do until (last.DATE);
set HAVE;
by date notsorted;
if var='c' then DUMMYVAR=1;
do until (last.DATE);
set HAVE;
by DATE notsorted;
if DATE=1 then ????????
end;
run;
Change your BY statements to match the grouping you are doing. And in the second loop add a simple OUTPUT; statement. Then your new dataset will have all the rows in your original dataset and the new variable DUMMYVAR.
data want;
do until (last.DATE);
set HAVE;
by case_id date;
if var='c' then DUMMYVAR=1;
end;
do until (last.DATE);
set HAVE;
by case_id date;
output;
end;
run;
This will create the variable DUMMYVAR with values of either 1 or missing. If you want the values to be 1 or 0 then you could either set it to 0 before the first DO loop. Or add if first.date then dummyvar=0; statement before the existing IF statement.

SAS Macro - Combining multiple tables into one, controlled by another table

I've come in late to a project and want to write a macro that normalises some data for export to a SQL Server.
There are two control tables...
- Table 1 (customers) has a list of customer unique identifiers
- Table 2 (hierarchy) has a list of table names
There are then n additional tables. One for each record in (hierarchy) (named in the SourceTableName field). With the form of...
- CustomerURN, Value1, Value2
I want to combine all of these tables into a single table (sample_results), with the form of...
- SourceTableName, CustomerURN, Value1, Value2
The only records that should be copied, however, should be for CustomerURNs that exist in the (customers) table.
I could do this in a hard coded format using proc sql, something like...
proc sql;
insert into
SAMPLE_RESULTS
select
'TABLE1',
data.*
from
Table1 data
INNER JOIN
customers
ON data.CustomerURN = customers.CustomerURN
<repeat for every table>
But every week new records are added to the hierarchy table.
Is there any way to write a loop that picks up the table name from the hierarchy table, then calls the proc sql to copy the data into sample_results?
You could concatenate all the hierarchy tables together, and do a single SQL join
proc sql ;
drop table all_hier_tables ;
quit ;
%MACRO FLAG_APPEND(DSN) ;
/* Create new var with tablename */
data &DSN._b ;
length SourceTableName $32. ;
SourceTableName = "&DSN" ;
set &DSN ;
run ;
/* Append to master */
proc append data=&DSN._b base=all_hier_tables force ;
run ;
%MEND ;
/* Append all hierarchy tables together */
data _null_ ;
set hierarchy ;
code = cats('%FLAG_APPEND(' , SourceTableName , ');') ;
call execute(code); /* run the macro */
run ;
/* Now merge in... */
proc sql;
insert into
SAMPLE_RESULTS
select
data.*
from
all_hier_tables data
INNER JOIN
customers
ON data.CustomerURN = customers.CustomerURN
quit;
Another way is to create a view so that it will always reflect the latest data in the metadata tables. The call execute function is used to read in the table names from the hierarchy dataset. Here is an example which you should be able to modify to suit your data, the last bit of code is the relevant one to you.
data class1 class2 class3;
set sashelp.class;
run;
data hierarchy;
input table_name $;
cards;
class1
class2
class3
;
run;
data ages;
input age;
cards;
11
13
15
;
run;
data _null_;
set hierarchy end=last;
if _n_=1 then call execute('proc sql; create view sample_results_view as ' );
if not last then call execute('select * from '||trim(table_name)||' where age in (select age from ages) union all ');
if last then call execute('select * from '||trim(table_name)||' where age in (select age from ages); quit;');
run;

How to extract month from a String representing a date in TSQL

In my SQL Server database I have the dates stored as char(12) in the following format:
yyyymmddhhmm
I didn't create the definition and I cannot modify it. I always dealt with this string at application level, by using C#.
Now I need to perform a task in TSQL and I need to group by month. Therefore I need to extract the month. Is there any TSQL function available for this task?
In case there is not, is it a good solution to create a stored procedure, getMonth(stringDate) that takes the string and extract the 4th and 5th characters from it? Can I use the clause:
group by getMonth(stringDate)
in my query? Thanks
You can;
SUBSTRING(fld, 5, 2)
Personally I would not create a UDF for something so simple (which is what you would consider rather than an SP) unless you find yourself needing to cast that string to DATETIMEs
You can use the following to get your month, since month is always 2 characters after the 4 character year.
declare #date char(12)
set #date = '201203220906'
select substring(#date, 5, 2)
results: 03
or another way to get it is, then you can group by the results in either query:
declare #date char(12)
set #date = '201203220906'
select Month(cast(left(#date, 8) as datetime))
Assuming
CREATE TABLE #Table(
DateValue char(12),
Value int)
INSERT INTO #Table VALUES ('20120110833', 1)
INSERT INTO #Table VALUES ('20120110833', 2)
INSERT INTO #Table VALUES ('20120110833', 3)
INSERT INTO #Table VALUES ('20120210833', 4)
INSERT INTO #Table VALUES ('20120210833', 5)
You can simply do this:
select
MONTH(CAST(LEFT(DateValue, 8) as datetime)) Month,
SUM(value)
FROM
#Table
GROUP BY
MONTH(CAST(LEFT(DateValue, 8) as datetime))
trim the hour/minute part, cast as datetime and apply MONTH function
For this specific case (date in char type with format yyyymmddhhmm), you can use in your query the next functions:
substring (to extract yyyymmdd),
convert (to get datetime value),
datepart (to get month component)
...then you can group by month (or whatever date component), change datecolumnname and tablename with appropiate values
select datepart(month,convert(datetime,substring(datecolumnname,1,8),112)),
count(datepart(month,convert(datetime,substring(datecolumnname,1,8),112)))
from tablename
group by datepart(month,convert(datetime,substring(datecolumnname,1,8),112))