Is it possible for me to do multiple actions in a single query or do I have to make a query for every change I would like to make?
I have a Column "Type" wich can have the string values "BOOL", "WORD" or "DINT"
In one single query, I would like to:
change all the "BOOL" into "DIGITAL"
change all the "WORD" into "UINT"
change all the "DINT" into "LONG"
Is it possible to do this in 1 single query (if yes, how?)
OR do i have to make several queries like this:
UPDATE DB_Total SET Type = 'DIGITAL'
WHERE Type='BOOL';
Thanks in advance!
Consider Switch() as an alternative to nested IIf() expressions.
With this data in DB_Total ...
id Type
1 BOOL
2 abc
3 <-- Type is Null
4 WORD
5 DINT
... this query updates DB_Total as shown below ...
UPDATE DB_Total
SET [Type] = Switch(
[Type]='BOOL','DIGITAL',
[Type]='WORD','UINT',
[Type]='DINT','LONG'
)
WHERE [Type] IN ('BOOL', 'WORD', 'DINT');
DB_Total after:
id Type
1 DIGITAL
2 abc
3
4 UINT
5 LONG
However you may find a different approach more convenient. Create a replacements table:
id old_type new_type
1 BOOL DIGITAL
2 WORD UINT
3 DINT LONG
Then this UPDATE statement will produce the same changes to DB_Total as the Switch() version.
UPDATE DB_Total AS d
INNER JOIN replacements AS r
ON d.Type = r.old_type
SET d.Type = [r].[new_type];
In the future, if you need to change or add/remove pairs of word replacements, you would only need to edit the replacements table. You would then not need to revise the query.
You can use a Nested IIF statement:
UPDATE DB_Total
SET Type = IIF(Type='BOOL','DIGITAL',
IIF(Type='WORD','UINT',
IIF(Type='DINT','LONG',Type)
)
)
WHERE Type IN ('BOOL', 'WORD', 'DINT');
(I'd usually write the IIF part all on one line, but I've done line breaks just so it is easier to read)
Related
Hi i want to update a specific row of my oracle database via apex. So i need to reach/address the specific row via where clause.
example entries:
GATTUNG
ART
UNTERART
ABART
VARIETÄT
AAA
AAA
AAA
NULL
NULL
AAA
AAA
NULL
NULL
AAA
AAA
AAA
NULL
NULL
NULL
Now i have two approaches.
first:
UPDATE TBL_PFLANZE
SET NAMEN =:P1_NAMEN
WHERE (GATTUNG = :P1_GATTUNG AND ART = :P1_ART_KREUZUNG)
AND ((UNTERART=:P1_UNTERART OR :P1_UNTERART IS NULL) AND (VARIETÄT=:P1_VARIETAET OR :P1_VARIETAET IS NULL) AND (ABART=:P1_ABART OR :P1_ABART IS NULL));
second:
UPDATE TBL_PFLANZE
SET NAMEN ='&P1_NAMEN.'
WHERE (GATTUNG = '&P1_GATTUNG.' AND ART = '&P1_ART_KREUZUNG.')
AND (UNTERART &P1_WHERE_UNTERART. AND VARIETÄT &P1_WHERE_VARIETAET. AND ABART &P1_WHERE_ABART.);
the differences of both approaches are the P1_WHERE_...variables.
the first one use for example :P1_UNTERART and contains the whole value
the second one use for example &P1_WHERE_UNTERART. and contains = '&P1_UNTERART.' OR IS NULL
my problem is:
the first one updates all entries if i only set GATTUNG and ART (if i do not specify one of the other variables)
the second will work, but is not the right approach as I should be using binding variables instead of &VAR.
So my question is, how can i use the first approach which the desired result... :(
Does this do the trick ? It will update the rows if any of the columns have the same value as the corresponding page item or the database column and page item are both null:
UPDATE tbl_pflanze
SET
namen = :P1_NAMEN
WHERE
( gattung = :P1_GATTUNG AND art = :P1_ART_KREUZUNG)
AND
( ( NVL(unterart,'X') = NVL(:P1_UNTERART,'X')) AND
( NVL(varietät,'X') = NVL(:P1_VARIETAET,'X')) AND
( NVL(abart,'X') = NVL(:P1_ABART,'X')) );
The way I see it, the 1st query is correct while the 2nd is wrong.
Why is it wrong? Because you're using strings. This:
SET NAMEN ='&P1_NAMEN.'
WHERE (GATTUNG = '&P1_GATTUNG.'
would want to put litally &P1_NAMEN. string into the NAMEN column for all rows whose GATTUNG column contains literally &P1_GATTUNG. string in it (and there's most probably none, so the 2nd query won't do anything, ever).
So, what is your problem, exactly? Why do you think that the 1st query doesn't work? Did you run the page in debug mode and reviewed debug results? Could it be that P1 page's items aren't stored into session state so UPDATE statement doesn't see them?
Also, where do you execute that UPDATE? As a process which runs after button is pressed? Something else?
I have the following sql data:
ID Company Name Customer Address 1 City State Zip Date
0108500 AAA Test Mish~Sara Newa Claims Chtiana CO 123 06FE0046
0108500 AAA.Test Mish~Sara Newa Claims Chtiana CO 123 06FE0046
1802600 AAA Test Company Ban, Adj.~Gorge PO Box 83 MouLaurel CA 153 09JS0025
1210600 AAA Test Company Biwel~Brce 97kehst ve Jacn CA 153 04JS0190
AAA Test, AAA.Test and AAA Test Company are considered as one company.
Since their data is messy I'm thinking either to do this:
Is there a way to search all the records in the DB wherein it will search the company name with almost the same name then re-name it to the longest name?
In this case, the AAA Test and AAA.Test will be AAA Test Company.
OR Is there a way to filter only record with company name that are almost the same then they can have option to change it?
If there's no way to do it via sql query, what are your suggestions so that we can clean-up the records? There are almost 1 million records in the database and it's hard to clean it up manually.
Thank you in advance.
You could use String matching algorithm like Jaro-Winkler. I've written an SQL version that is used daily to deduplicate People's names that have been typed in differently. It can take awhile but it does work well for the fuzzy match you're looking for.
Something like a self join? || is ANSI SQL concat, some products have a concat function instead.
select *
from tablename t1
join tablename t2 on t1.companyname like '%' || t2.companyname || '%'
Depending on datatype you may have to remove blanks from the t2.companyname, use TRIM(t2.companyname) in that case.
And, as Miguel suggests, use REPLACE to remove commas and dots etc.
Use case-insensitive collation. SOUNDEX can be used etc etc.
I think most Database Servers support Full-Text search ability, and if so there are some functions related to Full-Text search that support Proximity.
for example there is a Near function in SqlServer and here is its documentation https://msdn.microsoft.com/en-us/library/ms142568.aspx
You can do the clean-up in several stages.
Create new columns
Convert everything to upper case, remove punctuation & whitespace, then match on the first 6 to 10 characters (using self join). Assuming your table is called "vendor": add two columns, "status", "dupstr", then update as follows
/** Populate dupstr column for fuzzy match **/
update vendor v
set v.dupstr = left(upper(regex_replace(regex_replace(v.companyname,'.',''),' ','')),6)
;
Identify duplicate records
Add an index on the dupstr column, then do an update like this to identify "good" records:
/** Mark the good duplicates **/
update vendor v
set v.status = 'keep' --indicate keeper record
where
--dupes to clean up
exists ( select 1 from vendor v1 where v.dupstr = v1.dupstr
and v.id != v1.id )
and
( --keeper has longest name
length(v.companyname) =
( select max(length(v2.companyname)) from vendor v2
where v.dupstr = v2.dupstr
)
or
--keeper has latest record (assuming ID is sequential)
v.id =
( select max(v3.id) from vendor v3
where v.dupstr = v3.dupstr
)
)
group by v.dupstr
;
The above SQL can be refined to add "dupe" status to other records , or you can do a separate update.
Clean Up Stragglers
Report any remaining partial matches to be reviewed by a human (i.e. dupe records without a keeper record)
You can use SQL query with SOUDEX of DIFFRENCE
For example:
SELECT DIFFERENCE ('AAA Test','AAA Test Company')
DIFFERENCE returns 0 - 4 ( 4 = almost the same, 0 - totally diffrent)
See also: https://learn.microsoft.com/en-us/sql/t-sql/functions/difference-transact-sql?view=sql-server-2017
I want to improve this sql query without using UNION. When table_xx.uniqeId = 1 i want to use table_yy, when 2 i want to use table_ww. In fact i want this dynamic. i want to use an another table for uniqeId-table match because for future i can add extra table for example for table_xx.uniqeId = 3, use table_qq or something else. Can you suggest some idea, What can i use ?
Thanks.
SELECT
xx.info,
yy.value
FROM
table_xx xx,
table_yy yy
WHERE
xx.uniqeId = 1
UNION ALL
SELECT
xx.info,
yy.value
FROM
table_xx xx,
table_ww yy
WHERE
xx.uniqeId = 2
This would do it, provided that value is mandatory in yy and ww. But like Gordon Linoff already commented, a query like this doesn't necessary perform better. Most likely it won't, and it isn't much more readable as well. I would choose the union.
SELECT
xx.info,
nvl(yy.value, ww.value) as value
FROM
table_xx xx
LEFT JOIN table_yy yy ON xx.uniqeId = 1
LEFT JOIN table_ww ww ON xx.uniqeId = 2
WHERE
nvl(yy.value, ww.value) IS NOT NULL
But I think if the introduction of an extra xx_id also requires an extra table, it's a sign that your database structure is incorrect.
A better idea would be to add the uniqueid to the 'value' table as well, so you can easily join the right values on xx. This way, you can add extra ids and matching values as much as you like, without having to modify the database to add extra value tables.
SELECT
xx.info,
yy.value
FROM
table_xx xx
INNER JOIN table_yy yy ON yy.xx_uniqueid = xx.uniqueid
Whats the best way to do a query like this, which will update more than one row:
UPDATE B
SET col_a = 1
Where col_a = 0
I can load the entities then loop them to do the EntitySave for each one, however this seems like overkill. Should I use HQL to do the update? Can I use HQL to do the update?
You can absolutely run an update on more than one row using ORMExecuteQuery. This is an example of a project I worked on:
ORMExecuteQuery("UPDATE Part SET ReleaseDate = :ReleaseDate, ChangeNote = :ChangeNote WHERE ID IN (#Arguments.PartIDs#)", {ReleaseDate = Arguments.ReleaseDate, ChangeNote = Arguments.ChangeNote});
Easy as that... Notice that you specify the parameters as :VarName and feed them in as the second argument of the ORMExecuteQuery function.
Keep in mind I am using SQL 2000
I have two tables.
tblAutoPolicyList contains a field called PolicyIDList.
tblLossClaims contains two fields called LossPolicyID & PolicyReview.
I am writing a stored proc that will get the distinct PolicyID from PolicyIDList field, and loop through LossPolicyID field (if match is found, set PolicyReview to 'Y').
Sample table layout:
PolicyIDList LossPolicyID
9651XVB19 5021WWA85, 4421WWA20, 3314WWA31, 1121WAW11, 2221WLL99 Y
5021WWA85 3326WAC35, 1221AXA10, 9863AAA44, 5541RTY33, 9651XVB19 Y
0151ZVB19 4004WMN63, 1001WGA42, 8587ABA56, 8541RWW12, 9329KKB08 N
How would I go about writing the stored proc (looking for logic more than syntax)?
Keep in mind I am using SQL 2000.
Select LossPolicyID, * from tableName where charindex('PolicyID',LossPolicyID,1)>0
Basically, the idea is this:
'Unroll' tblLossClaims and return two columns: a tblLossClaims key (you didn't mention any, so I guess it's going to be LossPolicyID) and Item = a single item from LossPolicyID.
Find matches of unrolled.Item in tblAutoPolicyList.PolicyIDList.
Find matches of distinct matched.LossPolicyID in tblLossClaims.LossPolicyID.
Update tblLossClaims.PolicyReview accordingly.
The main UPDATE can look like this:
UPDATE claims
SET PolicyReview = 'Y'
FROM tblLossClaims claims
JOIN (
SELECT DISTINCT unrolled.LossPolicyID
FROM (
SELECT LossPolicyID, Item = itemof(LossPolicyID)
FROM unrolling_join
) unrolled
JOIN tblAutoPolicyList
ON unrolled.ID = tblAutoPolicyList.PolicyIDList
) matched
ON matched.LossPolicyID = claims.LossPolicyID
You can take advantage of the fixed item width and the fixed list format and thus easily split LossPolicyID without a UDF. I can see this done with the help of a number table and SUBSTRING(). unrolling_join in the above query is actually tblLossClaims joined with the number table.
Here's the definition of unrolled 'zoomed in':
...
(
SELECT LossPolicyID,
Item = SUBSTRING(LossPolicyID,
(v.number - 1) * #ItemLength + 1,
#ItemLength)
FROM tblLossClaims c
JOIN master..spt_values v ON v.type = 'P'
AND v.number BETWEEN 1 AND (LEN(c.LossPolicyID) + 2) / (#ItemLength + 2)
) unrolled
...
master..spt_values is a system table that is used here as the number table. Filter v.type = 'P' gives us a rowset with number values from 0 to 2047, which is narrowed down to the list of numbers from 1 to the number of items in LossPolicyID. Eventually v.number serves as an array index and is used to cut out single items.
#ItemLength is of course simply LEN(tblAutoPolicyList.PolicyIDList). I would probably also declared #ItemLength2 = #ItemLength + 2 so it wasn't calculated every time when applying the filter.
Basically, that's it, if I haven't missed anything.
If the PolicyIDList field is a delimited list, you have to first separate the individual policy IDs and create a temporary table with all of the results. Next up, use an update query on the tblLossClaims with 'where exists (select * from #temptable tt where tt.PolicyID = LossPolicyID).
Depending on the size of the table/data, you might wish to add an index to your temporary table.