Issue with the update cluase - sql-update

I am facing one issue in the update clause. I am trying to do the below:
update AM1 from DB.AM_7541 AM1,
(sel distinct TRIM(SB.LCDBDN) NEID, trim( leading '0' from sb.lcdmno) LCDMNO,
AM.Netw_equip
from
DB1.PLTL SB
inner join DB.AM_7541 AM
on trim( leading '0' from sb.lcdmno)=AM.accs_meth_num
where SB.LOAD_DATE in ( sel max(load_date),lcdmno,lcdbdn from DB1.PLTL where lcdmno not like ' ' and lcdmno is not null group by lcdmno, lcdbdn)
and SB.LCDBDN not like ''
) der
set Netw_equip=der.NEID
where AM1.accs_meth_num=der.lcdmno
I have to take the max(load_dt) grouped on lcdmno and lcdbdn.
I am getting error like too many expressions in the select clause.
Can you please help me on this.
Checked for dups:
sel NEID, LCDMNO, COUNT(*) from
(
sel distinct TRIM(SB.LCDBDN) NEID, trim( leading '0' from sb.lcdmno) LCDMNO,
AM.Netw_equip
from
DB1.PLTL SB
inner join DB.AM_7541 AM
on trim( leading '0' from sb.lcdmno)=AM.accs_meth_num
where SB.LOAD_DATE in ( sel max(load_date),lcdmno,lcdbdn from DB1.PLTL where lcdmno not like ' ' and lcdmno is not null group by lcdmno, lcdbdn)
and SB.LCDBDN not like '')
group by 1,2
having count(*)>1
--- 0 rows
Thanks,
Amit

The error is self-explaining, you return three columns in the Subquery but compare to a single row only.
Either rewrite using a Correlated Subquery or a multi-column Subquery:
update AM1 from DB.AM_7541 AM1,
( sel distinct TRIM(SB.LCDBDN) NEID,
trim( leading '0' from sb.lcdmno) LCDMNO,
AM.Netw_equip
from DB1.PLTL SB
inner join DB.AM_7541 AM
on trim( leading '0' from sb.lcdmno)=AM.accs_meth_num
where (SB.LOAD_DATE, sb.lcdmno, sb.lcdbdn) in
(
sel max(load_date),lcdmno,lcdbdn from DB1.PLTL
where lcdmno not like ' '
and lcdmno is not null
group by lcdmno, lcdbdn
)
and SB.LCDBDN not like ''
) der
set Netw_equip=der.NEID
where AM1.accs_meth_num=der.lcdmno
Btw, applying some formatting really simplifies reading/understanding a query.

Related

How to avoid this empty row using QUERY() in Google Sheets?

I've tried applying some criteria, but the row is still there.
This first empty row shouldn't be there.
Here is the formula, in case you'd like to help me correct it:
=if(I4<>"", { IFERROR(query(Datasets!X3:AU,"select AS, AT, AJ, AR where AS matches date '"&TEXT(DATEVALUE(I4),"yyyy-mm-dd")&"'",0),{"","","",""}); IFERROR(query(Datasets!BC3:BT,"select BC, BD, BS, BQ where BC matches date '"&TEXT(DATEVALUE(I4),"yyyy-mm-dd")&"'",0),{"","","",""}) }, UNIQUE({query(Datasets!X3:AU,"select AS, AT, ' ', SUM(AR) where AS is not null group by AS, AT, ' ' label ' '' ', SUM(AR) ' '",0); query(Datasets!BC3:BT,"select BC, BD, ' ', SUM(BQ) where BC is not null group by BC, BD, ' ' label ' '' ', SUM(BQ) ' '",0) }))
try:
=IF(I4<>"", {IFERROR(QUERY(Datasets!X3:AU,
"select AS,AT,AJ,AR
where AS matches date '"&TEXT(DATEVALUE(I4), "yyyy-mm-dd")&"'", ), {"","","",""});
IFERROR(QUERY(Datasets!BC3:BT,
"select BC,BD,BS,BQ
where BC matches date '"&TEXT(DATEVALUE(I4), "yyyy-mm-dd")&"'", ), {"","","",""})},
UNIQUE({QUERY(Datasets!X3:AU,
"select AS,AT,' ',SUM(AR)
where AS is not null
group by AS,AT,' '
label' ''',SUM(AR)''", );
QUERY(Datasets!BC3:BT,
"select BC,BD,' ',SUM(BQ)
where BC is not null
group by BC,BD,' '
label' ''',SUM(BQ)''", )}))

Regular expression - Remove special characters except single white space

From stack overflow, I got the standard reg expression
to eliminate -
a) special characters
b) digits
c) more than 2 spaces to single space
to include -
d) - (hyphen)
e) ' (single quote)
SELECT ID, REGEXP_REPLACE(REGEXP_REPLACE(forenames, '[^A-Za-z-]', ' '),'\s{2,}',' ') , REGEXP_REPLACE(REGEXP_REPLACE(surname, '[^A-Za-z-]', ' '),'\s{2,}',' ') , forenames, surname from table1;
Instead of 2 functions how to get the result in single function?
to include '(single quote) \' is not working in regexp_replace.
Thanks.
Oracle Setup:
CREATE TABLE test_data ( id, value ) AS
SELECT 1, '123a45b£$- ''c45d#{e''' FROM DUAL
Query:
SELECT ID,
REGEXP_REPLACE(
value,
'[^a-zA-Z'' -]| +( )',
'\1'
)
FROM test_data
Output:
ID | REGEXP_REPLACE(VALUE,'[^A-ZA-Z''-]|+()','\1')
-: | :--------------------------------------------
1 | ab- 'cde'
db<>fiddle here

Search every column, of every database of every schema for a regular expression

I'm working for a company undergoing acquisition at the moment. They use Oracle 11g and have a requirement for identifying all references to the current company name in their databases and having these listed by the schema/owner, table, column and number of occurrences in that column.
I've used the following with some success, as taken from another answer.
SET SERVEROUTPUT ON SIZE 100000
DECLARE
match_count INTEGER;
BEGIN
FOR T IN
(
SELECT owner, table_name, column_name
FROM all_tab_columns
WHERE
OWNER <> 'SYS' AND DATA_TYPE LIKE '%CHAR%'
) LOOP
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM ' || t.owner || '.' || t.table_name ||
' WHERE '||t.column_name||' = :1'
INTO MATCH_COUNT
USING 'NAME';
IF MATCH_COUNT > 0 THEN
dbms_output.put_line( t.owner ||' '|| t.table_name ||' '||t.column_name||' '||match_count );
END IF;
END LOOP;
END;
/
However it only finds literal strings of NAME and I also want to find Name, Name Shops, Name Accounts, Name someOtherStringICantGuess etc. So I think i should use a regular expression. I'm fine with the regular expression part, but it's how to incorporate it into the above functionality I'm unsure of. In fact i'm uncertain whether I will be adapting the above code, or doing something completely different.
One last thing: performance and duration of the run of the script are irrelevant and subordinate to the certainty of every column being checked. There is a dedicated environment that mimics production where this script will be deployed so it won't adversely affect the company's customers.
Thanks in advance.
EDIT: Just removed some company specific code...
The simplest method is to surround your search with upper.
SET SERVEROUTPUT ON SIZE 100000
DECLARE
-- set l_wildcard_search to true if you are using wildcards ('%'),
-- false if you want a straight match on the name
-- Wild card searches (like) are not able to use indexes whereas '='
-- potentially can.
l_wildcard_search CONSTANT BOOLEAN := FALSE;
match_count INTEGER;
--
l_searchvalue VARCHAR2 (100) := UPPER ('NAME');
l_cmd VARCHAR2 (200);
BEGIN
FOR t IN (SELECT owner, table_name, column_name
FROM all_tab_columns
WHERE owner NOT IN ('SYS', 'SYSTEM')
AND data_type LIKE '%CHAR%')
LOOP
BEGIN
l_cmd := 'SELECT COUNT(*) FROM '
|| t.owner
|| '.'
|| t.table_name
|| ' WHERE upper('
|| t.column_name
|| ')'
|| CASE WHEN l_wildcard_search THEN ' like ' ELSE ' = ' END
|| ':1';
DBMS_OUTPUT.put_line (l_cmd);
EXECUTE IMMEDIATE l_cmd INTO match_count USING l_searchvalue;
IF match_count > 0
THEN
DBMS_OUTPUT.put_line (t.owner || ' ' || t.table_name || ' ' || t.column_name || ' ' || match_count);
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error executing: ' || l_cmd);
END;
END LOOP;
END;
/
Here is your answer using regular expressions
SET SERVEROUTPUT ON SIZE 100000
DECLARE
match_count INTEGER;
l_searchvalue VARCHAR2 (100) := UPPER ('NAME');
l_cmd VARCHAR2 (200);
BEGIN
FOR t IN (SELECT owner, table_name, column_name
FROM all_tab_columns
WHERE owner NOT IN ('SYS', 'SYSTEM')
AND data_type LIKE '%CHAR%' and rownum < 10)
LOOP
BEGIN
l_cmd := 'SELECT COUNT(*) FROM '
|| t.owner
|| '.'
|| t.table_name
|| ' WHERE regexp_like('
|| t.column_name
|| ', :1)';
DBMS_OUTPUT.put_line (l_cmd);
EXECUTE IMMEDIATE l_cmd INTO match_count USING l_searchvalue;
IF match_count > 0
THEN
DBMS_OUTPUT.put_line (t.owner || ' ' || t.table_name || ' ' || t.column_name || ' ' || match_count);
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error executing: ' || l_cmd);
END;
END LOOP;
END;
/

Efficient SQL statement to encode text for NLP locutions

Background
A locution is a noun-phrase consisting of at least two words, such as:
black olive
hot pepper sauce
rose finn apple potato
The separate words black and olive are an adjective (black - JJ) and a noun (olive - NN). However, humans know that black olive is a noun (that differentiates it from, say, a green olive).
The problem here is how to most efficiently transform a list of normalized ingredient names (such as the list above) into a specific format for a natural language processor (NLP).
Example Data
The table can be created as follows:
CREATE TABLE ingredient_name (
id bigserial NOT NULL, -- Uniquely identifies the ingredient.
label character varying(30) NOT NULL
);
The following SQL statements show actual database records:
insert into ingredient_name (label) values ('alfalfa sprout');
insert into ingredient_name (label) values ('almond extract');
insert into ingredient_name (label) values ('concentrated apple juice');
insert into ingredient_name (label) values ('black-eyed pea');
insert into ingredient_name (label) values ('rose finn apple potato');
Data Format
The general format is:
lexeme1_lexeme2_<lexemeN> lexeme1_lexeme2_lexemeN NN
Given the list of words above, the NLP expects:
black_<olive> black_olive NN
hot_pepper_<sauce> hot_pepper_sauce NN
rose_finn_apple_<potato> rose_finn_apple_potato NN
The database has a table (recipe.ingredient_name) and a column (label). The labels are normalized (e.g., single space, lower case).
SQL Statement
The code that produces the expected results:
CREATE OR REPLACE VIEW ingredient_locutions_vw AS
SELECT
t.id,
-- Replace spaces with underscores
translate( t.prefix, ' ', '_' )
|| '<' || t.suffix || '>' || ' ' ||
translate( t.label, ' ', '_' )
|| ' NN' AS locution_nlp
FROM (
SELECT
id,
-- Ingredient name
label,
-- All words except the last word
left( label, abs( strpos( reverse( label ), ' ' ) - length( label ) ) + 1 ) AS prefix,
-- Just the last word
substr( label,
length( label ) - strpos( reverse( label ), ' ' ) + 2
) AS suffix
FROM
ingredient_name
WHERE
-- Limit set to ingredient names having at least one space
strpos( label, ' ' ) > 0
) AS t;
Question
What is a more efficient (or elegant) way to split the prefix (all words except the first) and suffix (just the last word) in the above code?
The system is PostgreSQL 9.1.
Thank you!
CREATE OR REPLACE VIEW ingredient_locutions_vw AS
SELECT
t.id,
format('%s_<%s> %s NN',
array_to_string(t.prefix, '_'),
t.suffix,
array_to_string(t.label, '_')
) AS locution_nlp
FROM (
SELECT
id,
-- Ingredient name
label,
-- All words except the last word
label[1:array_length(label, 1) - 1] AS prefix,
-- Just the last word
label[array_length(label, 1)] AS suffix
FROM (
select id, string_to_array(label, ' ') as label
from ingredient_name
) s
WHERE
-- Limit set to ingredient names having at least one space
array_length(label, 1) > 1
) AS t;
select * from ingredient_locutions_vw ;
id | locution_nlp
----+--------------------------------------------------------
1 | alfalfa_<sprout> alfalfa_sprout NN
2 | almond_<extract> almond_extract NN
3 | concentrated_apple_<juice> concentrated_apple_juice NN
4 | black-eyed_<pea> black-eyed_pea NN
5 | rose_finn_apple_<potato> rose_finn_apple_potato NN
(5 rows)

postgres - regex_replace in distinct clause?

Ok... changing the question here... I'm getting an error when I try this:
SELECT COUNT ( DISTINCT mid, regexp_replace(na_fname, '\\s*', '', 'g'), regexp_replace(na_lname, '\\s*', '', 'g'))
FROM masterfile;
Is it possible to use regexp in a distinct clause like this?
The error is this:
WARNING: nonstandard use of \\ in a string literal
LINE 1: ...CT COUNT ( DISTINCT mid, regexp_replace(na_fname, '\\s*', ''...
select trim(regexp_replace(E'\tfoo \t bar baz ', E'\\s+', ' ', 'g'))
replaces all (due to the 'g' flag) whitespace (\s) sequences (+) with a single space, then trims it, returning:
"foo bar baz"
The E is to indicate that the \ escape encoding is used.
With your new, edited question, you're probably looking for a query along the lines of:
select count(*) from (
select distinct
mid,
regexp_replace(na_fname, E'\\s*', '', 'g'),
regexp_replace(na_lname, E'\\s*', '', 'g')
from masterfile) as subquery;