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
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
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
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.
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,
......
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.