SELECT queries in a loop - sqlite

I am working on an sqlite3 shell.
SELECT * FROM tasks WHERE name in ("TaskA", "TaskD") LIMIT 5;
The above statement will print the first 5 rows only. Is there a way to write this statement so the first 5 rows from each of "TaskA" and "TaskD" results are printed?
In essence, I am trying to write a loop akin to:
FOR task in ("TaskA", "TaskD") SELECT * FROM tasks WHERE name = task LIMIT 5;
But I do not know the proper syntax.

Use ROW_NUMBER() window function:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY name ORDER BY rowid) rn
FROM tasks
WHERE name IN ("TaskA", "TaskD")
)
WHERE rn <= 5
I used the column rowid to define the order of the rows.
If there is another column in your table, like a date column, that can be used to define the order, you can replace rowid with that column.

Related

No more spool space in Teradata while trying Update

I'm trying to update a table with to many rows 388.000.
This is the query:
update DL_RG_ANALYTICS.SH_historico
from
(
SELECT
CAST((MAX_DIA - DIA_PAGO) AS INTEGER) AS DIAS_AL_CIERRE_1
FROM
(SELECT * FROM DL_RG_ANALYTICS.SH_historico A
LEFT JOIN
(SELECT ANO||MES AS ANO_MES, MAX(DIA) AS MAX_DIA FROM DL_RG_ANALYTICS.SH_CALENDARIO
GROUP BY 1) B
ON A.ANOMES = B.ANO_MES
) M) N
SET DIAS_AL_CIERRE = DIAS_AL_CIERRE_1;
Any help is apreciate.
This first thing I'd do is replace the SELECT * with only the columns you need. You can also remove the M derived table to make it easier to read:
UPDATE DL_RG_ANALYTICS.SH_historico
FROM (
SELECT CAST((MAX_DIA - DIA_PAGO) AS INTEGER) AS DIAS_AL_CIERRE_1
FROM DL_RG_ANALYTICS.SH_historico A
LEFT JOIN (
SELECT ANO || MES AS ANO_MES, MAX(DIA) AS MAX_DIA
FROM DL_RG_ANALYTICS.SH_CALENDARIO
GROUP BY 1
) B ON A.ANOMES = B.ANO_MES
) N
SET DIAS_AL_CIERRE = DIAS_AL_CIERRE_1;
What indexes are defined on the SH_CALENDARIO table? If there is a composite index of (ANO, MES) then you should re-write your LEFT JOIN sub-query to GROUP BY these two columns since you concatenate them together anyways. In general, you want to perform joins, GROUP BY and OLAP functions on indexes, so there will be less row re-distribution and they will run more efficiently.
Also, this query is updating all rows in the table with the same value. Is this intended, or do you want to include extra columns in your WHERE clause?

Converting a string to be used in in-clause Teradata

I have a string like this ('car, bus, train')
I want to convert it to be used in an in-clause. Basically I want to convert it to
('car','bus','train'). Please how do I do this in Teradata
I don't know how you are getting data like that, but if you have no control over that, you can use STRTOK_SPLIT_TO_TABLE.
select t.* from table (strtok_split_to_table(1,'car, bus, train',',')
returns (outkey integer,tokennum integer,resultstring varchar(25))) as t
Run by itself, that gives you:
outkey tokennum resultstring
1 1 car
1 2 bus
1 3 train
You can use that as a derived table and join it to the table you want to filter by. Something like:
select
<your table>.*
from
<your table>
inner join (select t.* from table (strtok_split_to_table(1,'car, bus, train',',')
returns (outkey integer,tokennum integer,resultstring varchar(25))) as t) dt
on yourtable.yourcolumn = dt.resultstring
here is the another way of spliting the input for n number of commas and use IN clause.
SELECT regexp_substr('car,bus,train','[^,]+',1,day_of_calendar) fields
FROM sys_calendar.calendar
WHERE day_of_calendar <= (CHAR('car,bus,train') - CHAR(oreplace('car,bus,train',',','')))+1;
Output of the Query
fields
~~~~~~~~
bus
car
train
Here is the systax to use in where clause
SELECT * FROM <your table>
WHERE yourtable.requiredColumn in
(
SELECT regexp_substr('car,bus,train','[^,]+',1,day_of_calendar) fields
FROM sys_calendar.calendar
WHERE
day_of_calendar <= (CHAR('car,bus,train') - CHAR(oreplace('car,bus,train',',','')))+1
);
Basically what we are doing here is splitting the string for each comma and below function is calculating number of commas in the string
(CHAR('car,bus,train') - CHAR(oreplace('car,bus,train',',','')))+1

sort semicolon separated values per row in a column

I want to sort semicolon separated values per row in a column. Eg.
Input:
abc;pqr;def;mno
xyz;pqr;abc
abc
xyz;jkl
Output:
abc;def;mno;pqr
abc;pqr;xyz
abc
jkl;xyz
Can anyone help?
Perhaps something like this. Breaking it down:
First we need to break up the strings into their component tokens, and then reassemble them, using LISTAGG(), while ordering them alphabetically.
There are many ways to break up a symbol-separated string. Here I demonstrate the use of a hierarchical query. It requires that the input strings be uniquely distinguished from each other. Since the exact same semicolon-separated string may appear more than once, and since there is no info from the OP about any other unique column in the table, I create a unique identifier (using ROW_NUMBER()) in the most deeply nested subquery. Then I run the hierarchical query to break up the inputs and then reassemble them in the outermost SELECT.
with
test_data as (
select 'abc;pqr;def;mno' as str from dual union all
select 'xyz;pqr;abc' from dual union all
select 'abc' from dual union all
select 'xyz;jkl' from dual
)
-- End of test data (not part of the solution!)
-- SQL query begins BELOW THIS LINE.
select str,
listagg(token, ';') within group (order by token) as sorted_str
from (
select rn, str,
regexp_substr(str, '([^;]*)(;|$)', 1, level, null, 1) as token
from (
select str, row_number() over (order by null) as rn
from test_data
)
connect by level <= length(str) - length(replace(str, ';')) + 1
and prior rn = rn
and prior sys_guid() is not null
)
group by rn, str
;
STR SORTED_STR
--------------- ---------------
abc;pqr;def;mno abc;def;mno;pqr
xyz;pqr;abc abc;pqr;xyz
abc abc
xyz;jkl jkl;xyz
4 rows selected.

How do you match multiple text in multiple column in a table with SQLite FTS3?

I'm searching for Multiple text in multiple column of Virtual Table. I have checked this thread, this search for a single word in multiple column.
I checked with following
SELECT * FROM table WHERE table MATCH (('A:cat OR C:cat') AND ('A:dog OR C:dog')
but it seems AND condition not working.
EDIT I have tried with following,
Select count (*) FROM Table1 WHERE TBL_VIRTUAL MATCH (('A:D* AND B:D* AND C:D*') OR ('A:tar* AND B:tar* AND C:tar*'));
Select count (*) FROM Table1 WHERE TBL_VIRTUAL MATCH (('A:D* AND B:D* AND C:D*') AND ('A:tar* AND B:tar* AND C:tar*'));
These both query return me same 109 result. Then I tried what #redneb mention in below answer:
SELECT * FROM table WHERE table MATCH '(A:D* OR B:D* OR C: D*) AND (A:tar* OR B:tar* OR C:tar*)'
SELECT * FROM table WHERE table MATCH '(A:D* OR B:D* OR C: D*) OR (A:tar* OR B:tar* OR C:tar*)'
But this return 0 result.
Any suggestion what I'm missing here!!
Try this instead:
SELECT *
FROM mytable
WHERE mytable MATCH '(A:cat OR C:cat) AND (A:dog OR C:dog)';
However, I suspect that the following query will perform faster:
SELECT *
FROM mytable
WHERE mytable MATCH '(A:cat AND C:dog) OR (A:dog AND C:cat)';
and is equivalent to the first one.
Edit: Here's a complete example. Let's create and populate a table first:
CREATE VIRTUAL TABLE mytable USING fts3(A, C);
INSERT INTO mytable VALUES
('foo','bar'),
('dog','dog'),
('cat','cat'),
('dog','cat'),
('cat','dog');
Then the query works as expected:
sqlite> SELECT * FROM mytable WHERE mytable MATCH '(A:cat AND C:dog) OR (A:dog AND C:cat)';
A C
---------- ----------
dog cat
cat dog
For OR condition type OR between i.e. : MATCH ('A:cat OR C:cat')
For AND condition just don't type anything i.e. : MATCH ('A:cat C:cat')

Assigning the rownnum values in a column in the table in ORACLE database?

Example:
It does not work.
UPDATE column_name SET rownum FROM table_name
This work!
UPDATE table_name SET column_name = rownum;
This works but the update is performed incorrectly
SELECT * FROM table_name ORDER BY column_name;
UPDATE table_name SET column_name = rownum;
I wish the following update behavior:
Note:'rownum ' It is not a physical column of the table
/*
pc_comentario = tableName
cod_comentario = columnName (Reference column for sorting)
dtc_andamento = columnDay (Reference column to update the "columnName" according to the order of this column)
*/
rownum | columnName | columnDay
1 1 day 1
2 5 day 5
3 7 day 2
After change with update
rownum | columnName (Update this column) | columnDay (sort by this column)
1 1 day 1
2 2 day 2
3 3 day 5
ALMOST DONE! this column 'cod_comentario_1 "which was materialized in RAM is correct. I need this column" cod_comentario_1 "that does not exist in the table is acknowledged in the consultations with java.
SELECT cod_comentario, dtc_andamento, cod_processo ,
ROW_NUMBER()
OVER (PARTITION BY cod_processo
ORDER BY dtc_andamento) cod_comentario_1
FROM pc_comentario
upadate do not work this way:
UPDATE (
SELECT cod_processo
ROW_NUMBER()
OVER (PARTITION BY cod_processo
ORDER BY dtc_andamento)cod_comentario_1
FROM pc_comentario
) SET cod_comentario_1)
order by Seq
I must enter the values of this consultation in a new column that I created
SELECT
ROW_NUMBER()
OVER (PARTITION BY cod_processo
ORDER BY dtc_andamento DESC)
FROM pc_comentario
Try:
UPDATE table_name
SET column_name = rownum
Shouldn't it be like below rather; I believe UPDATE statement has no FROM clause
UPDATE table_name SET column_name = rownum;
Again, it will work only if rownum is an existing column in your table. If you are trying to use Oracle rownum instead then consider using row_number() function rather
update table_name set column_name =
select rn from ( select column_name, row_number() over (order by column_name) rn
from table_name ) xx;
As you state yourself, rownum is a virtual column. It assigns a sequential value to each row of a particular result set. Which means that the row number of a row could be completely different in the result set of a different query.
If you really want to show the row number as part of the result set, specify it as you would any column:
select rownum as columnName, columnDay
from table
order by ...;

Resources