Many Updates -> One Update? - sql-server

Once a month we receive a file from another company and we need to adapt it to our database (in SQL Server). For this we run several updates that take a long time.
Is there any way to "convert" all these updates into a single statement so it runs through the table only once? (it's a really big table!).
We are using something like this right now:
update Table1 set column01 = 0 where column01 = ' ' or column01 = '';
update Table1 set column02 = 0 where column02 = ' ' or column02 = '';
update Table1 set column03 = 0 where column03 = ' ' or column03 = '';
update Table1 set column04 = 0 where column04 = ' ' or column04 = '';
update Table1 set column05 = 0 where column05 = ' ' or column05 = '';
update Table1 set column06 = 0 where column06 = ' ' or column06 = '';
update Table1 set column07 = 0 where column07 = ' ' or column07 = '';
update Table1 set column08 = 0 where column08 = ' ' or column08 = '';
update Table1 set column09 = 0 where column09 = ' ' or column09 = '';
update Table1 set column10 = 0 where column10 = ' ' or column10 = '';
update Table1 set column11 = 0 where column11 = ' ' or column11 = '';
update Table1 set column12 = 0 where column12 = ' ' or column12 = '';
update Table1 set column13 = 0 where column13 = ' ' or column13 = '';
update Table1 set column14 = 0 where column14 = ' ' or column14 = '';
update Table1 set column15 = 0 where column15 = ' ' or column15 = '';
update Table1 set column16 = 0 where column16 = ' ' or column16 = '';
update Table1 set column17 = 0 where column17 = ' ' or column17 = '';
update Table1 set column18 = 0 where column18 = ' ' or column18 = '';
update Table1 set column19 = 0 where column19 = ' ' or column19 = '';

You could use CASE ... WHEN like this
update Table1 set
column01 = CASE when column01 = ' ' or column01 = '' then 0 ELSE column01 END,
column02 = CASE when column02 = ' ' or column02 = '' then 0 ELSE column02 END,
......
column19 = CASE when column19 = ' ' or column19 = '' then 0 ELSE column19 END

Related

SOQL Group by IN Salesforce

String query = 'SELECT id,CreatedById,Product.Id,POCGrades__c ,fm_pocname__c,product.Name ,Visit.placeId, fm_poccode__c, createdby.LastName,Visit.LastModifiedDate, createddate, ActualBooleanValue'
+ ' FROM retailvisitkpi'
+ ' WHERE createddate = last_month and '
+ ' ( Product.Id = \'01t5j000003tszWAAQ\''
+ ' OR Product.Id = \'01t5j000003tszWAAQ\''
+ ' OR Product.Id = \'01t5j000003tt5nAAA\''
+ ' OR Product.Id = \'01t5j000003tsznAAA\''
+ ' OR Product.Id = \'01t5j000003tt1zAAA\''
+ ' OR Product.Id = \'01t5j000003tt7AAAQ\''
+ ' )';
I am having trouble to removes duplicate records based on Visit.placeID, can anybody help me out with soql
Just use hashmaps with the resulting query?
Map<String, retailvisitkpi__c> mapOfItems = new Map<String, retailvisitkpi__c>();
That will remove all the duplicates based on the Visit Place ID

proc or function that will loop over each database in snowflake and list tables with empty rows

Can someone help find these zero row tables?
CREATE OR REPLACE PROCEDURE checkrows()
RETURNS VARIANT
LANGUAGE JAVASCRIPT
AS
$
function ExecuteNonQuery(querystring) {
var out = '';
cmd1 = {sqlText: select * from information_schema.tables where rows_count = 0;};
stmt = snowflake.createStatement(cmd1);
var rs;
try{
rs = stmt.execute();
rs.next();
out = "SUCCESS: " + rs.getColumnValue(0);
}
catch(err) {
throw "ERROR: " + err.message.replace(/\n/g, " ");
}enter code here
return out;
}
$$;
If you have a use case that it's okay to get row counts that are several minutes older than the last change (generally 15-90 minutes but up to 3 hours), you can simply run this:
select * from "SNOWFLAKE"."ACCOUNT_USAGE"."TABLES"
where TABLE_TYPE = 'BASE TABLE' and DELETED is null and ROW_COUNT = 0;
Edit: Since this needs to be automated, this SP will return a variant array with objects containing the db, schema, and table name of all tables with zero rows.
create or replace procedure FIND_EMPTY_TABLES(DATABASE_PATTERN string) -- Use .* for all databases in account. It will skip SNOWFLAKE and SNOWFLAKE_SAMPLE_DATA
returns variant
language javascript
execute as owner
as
$$
class Account {constructor(databases){this.databases = databases;}}
class Database {constructor(name) {this.name = name;}}
class Query{constructor(statement){this.statement = statement;}}
var account = getDatabasesInAccount(DATABASE_PATTERN);
var out = [];
for (var i = 0; i < account.databases.length; i++) {
out = out.concat(rsToJSON(getQuery(
`select TABLE_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_OWNER
from ${account.databases[i].name}.INFORMATION_SCHEMA.TABLES
where TABLE_TYPE = 'BASE TABLE' and ROW_COUNT = 0`)));
}
return out;
//------
function getQuery(sql){
cmd1 = {sqlText: sql};
var query = new Query(snowflake.createStatement(cmd1));
query.resultSet = query.statement.execute();
return query;
}
function executeSingleValueQuery(columnName, queryString) {
cmd = {sqlText: queryString};
stmt = snowflake.createStatement(cmd);
var rs;
rs = stmt.execute();
rs.next();
return rs.getColumnValue(columnName);
}
function getDatabasesInAccount(databasePattern){
const SYSTEM_DB_NAMES = ["SNOWFLAKE", "SNOWFLAKE_SAMPLE_DATA"];
var db = executeSingleValueQuery("name", "show databases");
var i = 0;
var dbRS = getResultSet(`select DATABASE_NAME from "${db}".INFORMATION_SCHEMA.DATABASES where rlike (DATABASE_NAME, '${databasePattern}');`);
var databases = [];
var db;
while (dbRS.next()){
db = new Database(dbRS.getColumnValue("DATABASE_NAME"));
if (!SYSTEM_DB_NAMES.includes(db)) {
databases.push(db);
}
}
return new Account(databases);
}
function getResultSet(sql){
let cmd = {sqlText: sql};
let stmt = snowflake.createStatement(cmd);
let rs = stmt.execute();
return rs;
}
function rsToJSON(query) {
var i;
var row = {};
var table = [];
while (query.resultSet.next()) {
for(col = 1; col <= query.statement.getColumnCount(); col++) {
row[query.statement.getColumnName(col)] = query.resultSet.getColumnValue(col);
}
table.push(row);
}
return table;
}
$$;
call FIND_EMPTY_TABLES('.*'); -- .* is the RegExp pattern that tell it to check all databases except built-in ones.
Dirty and quick option adding to gregs excellent answer ... obviously if you like the results add 'create or replace zero_row_count_base_tables as ...' .... set it to re-create the view maybe weekly/daily then run the view when you want.
SELECT
' SELECT TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME from UTIL_DB.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = \'BASE TABLE\' AND ROW_COUNT > 0 '
UNION
SELECT concat( 'UNION SELECT TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME
FROM ', DATABASES.DATABASE_NAME,'.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = \'BASE TABLE\' AND ROW_COUNT > 0 ')
FROM UTIL_DB.INFORMATION_SCHEMA.DATABASES

Boolean conditions in SQL where clause

I wanted to write an sql query to fetch data as:
1. when param = 'all' it should list data across the table
2. when param = 'yes' it should list data where invoicenumber is not empty.
3. when param = 'no' it should list data where invoicenumber is empty.
i tried below query for yes and no
declare #invoiced as nvarchar(10) = 'no'
select * from OrderSummary
where
((#invoiced = 'yes') or (InvoiceNumber = ''))
and
((#invoiced = 'no') or (InvoiceNumber <> ''))
now i also want to incorporate all condition, could anyone suggest how could i achieve that
declare #invoiced as nvarchar(10) = 'no'
select * from OrderSummary
where
#invoiced = 'all'
OR
(#invoiced = 'yes' AND InvoiceNumber <> '')
OR
(#invoiced = 'no' AND InvoiceNumber = '')
Try this
declare #invoiced as nvarchar(10) = 'no'
select
*
from OrderSummary
where
(
#invoiced = 'all'
OR
(
#invoiced = 'yes'
AND
InvoiceNumber <> ''
)
OR
(
#invoiced = 'no'
AND
InvoiceNumber = ''
)
)
It should fulfill your requirement.
declare #invoiced as nvarchar(10) = 'no'
select * from OrderSummary
where
((#invoiced in ('all','no')) OR (#invoiced = 'yes' AND InvoiceNumber <> ''))
and
((#invoiced in ('all','yes')) OR (#invoiced = 'no' AND InvoiceNumber = ''))
and
(#invoiced in ('no','yes'))
declare #invoiced as nvarchar(10) = 'no'
select * from OrderSummary
where
((#invoiced = 'yes') and (InvoiceNumber <> '') )
or
((#invoiced = 'no') and ( (InvoiceNumber = '') or (InvoiceNumber = null)))
or (#invoiced = 'all')
Please update this query with above query.

SQL Server Merge with case?

Hello guys here with another question, regarding sql server 2008 r2 this time about the merge, is it possible to have a case inside the update portion of the merge?
Because its telling me
Msg 156, Level 15, State 1, Line 9
Incorrect syntax near the keyword 'CASE'.
MERGE INTO PERSONAFISICA AS TARGET
USING dbo.#temp1 AS SOURCE
ON TARGET.RFC = SOURCE.RFC AND TARGET.APATERNO = SOURCE.APELLIDO_PATERNO AND
TARGET.AMATERNO = SOURCE.Apellido_Materno
WHEN MATCHED THEN
UPDATE SET
TARGET.NUM_CLIENTE = 0,
TARGET.NOMBRE1 = LEFT(SOURCE.Nombre,CHARINDEX(' ', SOURCE.NOMBRE + ' ') -1),
CASE
WHEN LEN(SOURCE.NOMBRE) - LEN(REPLACE(SOURCE.NOMBRE,' ','')) >= 1
THEN
TARGET.NOMBRE2 = SUBSTRING(SOURCE.NOMBRE, CHARINDEX(' ', SOURCE.NOMBRE)+1, LEN(SOURCE.NOMBRE))
ELSE '' END,
TARGET.APATERNO = SOURCE.Apellido_Paterno,
TARGET.AMTERNO = SOURCE.Apellido_Materno,
CASE
WHEN SOURCE.SEXO = 'F'
THEN TARGET.IDGENERO = 2
WHEN SOURCE.SEXO = 'M'
THEN TARGET.IDGENERO = 1
ELSE TARGET.IDGENERO = 0
END,
CASE
WHEN SOURCE.ESTADO_CIVIL = '0'
THEN TARGET.idestado_civil = 0
WHEN SOURCE.ESTADO_CIVIL = 'C'
THEN TARGET.idestado_civil = 1
WHEN SOURCE.ESTADO_CIVIL = 'D'
THEN TARGET.idestado_civil = 2
WHEN SOURCE.ESTADO_CIVIL = 'S'
THEN TARGET.idestado_civil = 3
WHEN SOURCE.ESTADO_CIVIL = 'V'
THEN TARGET.idestado_civil = 5
WHEN SOURCE.ESTADO_CIVIL = 'U'
THEN TARGET.idestado_civil = 6
ELSE TARGET.idestado_civil = 0
END,
TARGET.idregimen = 0,
TARGET.saludo = SOURCE.SALUDO,
TARGET.conyuge_nombre1 = '',
TARGET.conyuge_nombre2 = '',
TARGET.conyuge_apaterno = '',
TARGET.conyuge_nombre2 = '',
TARGET.dependiente = 0,
TARGET.edad_dependiente = '',
TARGET.ididentificacion = 0,
TARGET.fecha_nacimiento = '1800-01-01',
TARGET.rfc = SOURCE.RFC,
TARGET.CURP = '',
TARGET.idnacionalidad = 0,
TARGET.email = SOURCE.Email_Personal,
TARGET.idescolaridad = SOURCE.Escolaridad
WHEN NOT MATCHED THEN
INSERT (num_cliente, nombre1, nombre2, apaterno, amaterno, idgenero, idestado_civil,
idregimen, saludo, conyuge_nombre1, conyuge_nombre2, conyuge_apaterno, conyuge_amaterno, dependiente,
edad_dependiente, ididentificacion, fecha_nacimiento, rfc, curp, idnacionalidad, email, idescolaridad)
VALUES (0, LEFT(nombre,CHARINDEX(' ',nombre + ' ')-1) AS [Primer Nombre],
CASE WHEN LEN(nombre) - LEN(REPLACE(nombre,' ','')) >= 1 THEN SUBSTRING(nombre, CHARINDEX(' ', nombre)+1, LEN(nombre)) ELSE '' END AS [Segundo Nombre],
Apellido_Paterno,Apellido_Materno)
CASE
WHEN SEXO = 'F' THEN 2
WHEN SEXO = 'M' THEN 1
ELSE 0
END,
CASE
WHEN Estado_Civil = '0' THEN 0
WHEN Estado_Civil = 'C' THEN 1
WHEN Estado_Civil = 'D' THEN 2
WHEN Estado_Civil = 'S' THEN 3
WHEN Estado_Civil = 'V' THEN 5
WHEN Estado_Civil = 'U' THEN 6
ELSE 0
END, 0, Saludo,'','','','',0,'',0,'1800-01-01',RFC,'',0,Email_Personal,Escolaridad
You can't use a case in that way in an update. It needs to be like ...
UPDATE table
SET value1 = CASE
WHEN a.blah = b.blah THEN foo
WHEN a.blah > b.blah THEN bar
ELSE NULL
END,
value2 = 5,
......

execute result of select statement

How can I execute the results of my select query. The query below gives me some SQL statements back as result. I want to execute does statements, how to do this? All this is executed in SQL Sever Management Studio.
Query:
SELECT 'UPDATE Rolecopy SET PartofFT = ''' + R2.PlayedbyOT + ''', OriginalOT = ''' + R.PlayedbyOT + ''' WHERE RoleNo = ' + CAST(R.RoleNo AS VARCHAR) + CHAR(13)
FROM Role R INNER JOIN Role R2
ON R.PartofFT = R2.PartofFT AND R.RoleNo <> R2.RoleNo
WHERE EXISTS (
SELECT PG.RoleNo
FROM V_PurposeGrouping PG
WHERE R.PartofFT = PG.PartofFT
AND R.RoleNo <> PG.RoleNo
)
Result:
UPDATE Rolecopy SET PartofFT = 'Student', OriginalOT = 'Teacher' WHERE RoleNo = 5.00
UPDATE Rolecopy SET PartofFT = 'Project', OriginalOT = 'Teacher' WHERE RoleNo = 8.00
UPDATE Rolecopy SET PartofFT = 'Project', OriginalOT = 'description' WHERE RoleNo = 10.00
UPDATE Rolecopy SET PartofFT = 'Student', OriginalOT = 'Project' WHERE RoleNo = 15.0
0
Try using your first query to open a cursor, then within the loop execute the result string as dynamic SQL.
declare commands cursor for
SELECT 'UPDATE Rolecopy SET PartofFT = ''' + R2.PlayedbyOT + ''', OriginalOT = ''' + R.PlayedbyOT + ''' WHERE RoleNo = ' + CAST(R.RoleNo AS VARCHAR) + CHAR(13)
FROM Role R INNER JOIN Role R2
ON R.PartofFT = R2.PartofFT AND R.RoleNo <> R2.RoleNo
WHERE EXISTS (
SELECT PG.RoleNo
FROM V_PurposeGrouping PG
WHERE R.PartofFT = PG.PartofFT
AND R.RoleNo <> PG.RoleNo
)
declare #cmd varchar(max)
open commands
fetch next from commands into #cmd
while ##FETCH_STATUS=0
begin
exec(#cmd)
fetch next from commands into #cmd
end
close commands
deallocate commands
Try using this :
SELECT 'UPDATE Rolecopy SET PartofFT = ''' + R2.PlayedbyOT + ''', OriginalOT = ''' + R.PlayedbyOT + ''' WHERE RoleNo = ' + CAST(R.RoleNo AS VARCHAR) + CHAR(13)
FROM Role R INNER JOIN Role R2
ON R.PartofFT = R2.PartofFT AND R.RoleNo <> R2.RoleNo
WHERE EXISTS (
SELECT PG.RoleNo
FROM V_PurposeGrouping PG
WHERE R.PartofFT = PG.PartofFT
AND R.RoleNo <> PG.RoleNo
)
FOR XML PATH ('')
For which the result is going into one string column:
UPDATE Rolecopy SET PartofFT = 'Student', OriginalOT = 'Teacher' WHERE RoleNo = 5.00
UPDATE Rolecopy SET PartofFT = 'Project', OriginalOT = 'Teacher' WHERE RoleNo = 8.00
UPDATE Rolecopy SET PartofFT = 'Project', OriginalOT = 'description' WHERE RoleNo = 10.00
UPDATE Rolecopy SET PartofFT = 'Student', OriginalOT = 'Project' WHERE RoleNo = 15.0
All in the same column.

Resources