Improve sqlite query Where field in to exists - sqlite

Here's my simplified working query:
select fields, sum(otherFields)
from table1
where table1.field1 in (Select table2.field1
from table2
where table1.id=table2.id
order by table2.date desc limit 100)
group by fields
As you can see, I need from table1 only the rows that are in table2 but these ones filtered by last newer 100.
The query takes a bit too long, so I've tried to replace the in with exists
select fields, sum(otherFields)
from table1
where exists (Select table2.field1
from table 2
where table1.id=table2.id
and table1.field=table2.fields
order by table2.date desc limit 100)
group by fields
While this would work for queries that don't use limit in my case it does not work properly.
So, how can I properly filter the result from table1 in relation with only a limited number of rows from table2?

Related

Delete duplicate rows in sqlite database

I want to delete duplicate rows in a sqlite database. I found this code online to do it:
DELETE FROM table1
WHERE ROWID NOT IN (
SELECT min(rowid)
FROM table1
GROUP BY col1, col2
)
But the issue is that my database contains 50+ columns and I don't want to write all the column names in group by. Is there a workaround to group by all the columns?
I am new to this so I may be missing something simple.
In a GROUP BY clause you must enumerate all the columns.
For your case, I think it's better to create another table table2 with all the distinct rows of table1, then delete all rows of table1 and finally insert all rows from table2 to table1:
CREATE TABLE table2 AS SELECT DISTINCT * FROM table1;
DELETE FROM table1;
INSERT INTO table1 SELECT * FROM table2;
DROP TABLE table2;
See a simplified demo.

update (overwrite) an entire record (all columns) in sqlite

When I am copying rows from one table to another, there is a convenient syntax:
INSERT INTO table1 SELECT * FROM table2 WHERE <table 2 rows have some property>
But what if I want to overwrite entire existing rows in table1 with entire rows from table2? So I want something like:
UPDATE table1 SET * FROM table2 WHERE <table 1 and 2 rows match on some key field>
But from what I can tell, the only way to do this is to enumerate the columns being set one by one (set table1.columnA = table2.columnA, table1.columnB = table2.columnB, and so on). Is there some way to say "do it for all the columns" when using UPDATE like there is when using INSERT? If not, why not?
(I guess I could delete all rows from table1 with the given property, and then use the INSERT INTO table1 SELECT * syntax to bring in the replacement rows from table2. But that seems like it leaves a bunch of unwanted deleted rows in the database needing to be vacuumed at some point, as opposed to a clean UPDATE where there are no deleted records? Or maybe I'm not understanding the efficiency of a bunch of deletes followed by a bunch of inserts?)
There is no such syntax for exactly what you have in mind, and I think you will need to SET each column separately. Also, SQLite does not support a direct update join syntax, but we may use correlated subqueries:
UPDATE table1
SET table1.columnA = (SELECT columnA FROM table2 WHERE table1.col = table2.col),
SET table1.columnB = (SELECT columnB FROM table2 WHERE table1.col = table2.col),
SET table1.columnC = (SELECT columnC FROM table2 WHERE table1.col = table2.col);

I want to count ocurrences of a Text in a Field in MariaDB

In MariaDB, I want to insert count ocurrences of a Text in a Field in another table.
something like:
Insert Into UniqueFacts (Text, Frecuency)
(SELECT DISTINCT(Fact) , count(*) FROM AllFacts group by Fact)
But this sentence no insert frecuencies.
Thank you.
DISTINCT is not a function. What you have is the same as
SELECT DISTINCT
Fact, COUNT(*)
FROM ...
DISTINCT and GROUP BY are always(?) redundant with each other.
To fix your query, simply remove one word: DISTINCT; keep the GROUP BY.

Can we delete duplicate records from a table in teradata without using intermediate table

Can we delete duplicate records from a multiset table in teradata without using intermediate table.
Suppose we have 2 rows with values
1, 2, 3
and 1, 2, 3
in my multiset table then after delete i should have
only one row i.e. 1, 2, 3.
You can't unless the ROWID usage has been enabled on your system (and probablity is quite low). You can easily test it by trying to explain a SELECT ROWID FROM table;
Otherwise there are two possible ways.
Low number of duplicates:
create a new table as result of SELECT all columns FROM table GROUP BY all columns HAVING COUNT(*) > 1;
DELETE FROM tab WHERE EXISTS (SELECT * FROM newtab WHERE...)
INSERT INTO tab SELECT * FROM newtab
High number of duplicates:
copy to a new table using SELECT DISTINCT * or copy to a SET TABLE to get rid of the duplicates and then re-INSERT back
Use the same approach, but create a volatile table in the middle.
CREATE VOLATILE MULTISET TABLE TEMPDB.TEMP_DUP_ID (
Row_ID DECIMAL(31,0)
) PRIMARY INDEX (Row_ID)
ON COMMIT PRESERVE ROWS;
INSERT INTO TEMPDB.TEMP_DUP_ID
SELECT ROW_ID
FROM DB.TABLE T
QUALIFY ROW_NUMBER() OVER (PARTITION BY DUP ORDER BY DUP DESC) > 1
Then use the table to delete.
Ideally you will have unique key per row, otherwise, you will need to manipulate the data a bit more to generate one (with row_number() for instance... This is just a recommendation).
---Without creating intermediate table
delete FROM ORGINAL_TABLE WHERE (COL1, 2) in (select COL1, count() from ORGINAL_TABLE
GROUP BY 1
HAVING COUNT() >1 )
and DUPLICATE_BASED_COL >1; -------Delete one row(keep it)
If you have duplicates and want to delete one row, then we need to use the last line in the sql, if we want to delete both rows than, ignore the condition.
create table without dup
CREATE TABLE new AS (SELECT DISTINCT * FROM old) WITH DATA;
verify
select * from new;
drop the original one
drop table old;
rename the new table as original
RENAME TABLE new to old;
verify
select * from old;
SEL * FROM THE_TABLE_Containing_duplications
QUALIFY (ROW_number() over(partition by duplicated_column order by duplicated_column)=1) --keep only one occurence (the first one)

How can we fetch top 3 data value from database

There is three field in my data base id(primary key),name, salary
I want fetch top 3 salary from the database.
Use LIMIT to get top 3 after ordering, as such:
SELECT *
FROM myTable
ORDER BY salary DESC
LIMIT 3;
SELECT * FROM your_table ORDER BY id DESC;
SELECT [column(s)]
FROM [table]
ORDER BY [column(s)] [ASC, DESC];
For more information check here:
http://www.sqlite.org/lang_select.html
SQL has an ORDER BY clause that allows you do order the result set by any column/columns, ascending and descending.
For your particular question:
SELECT Id, Name
FROM myTable
ORDER BY Id DESC;
See this SO question (SQLite - sorting a table).

Resources