In query in SQLite - sqlite

"IN" query is not working. Please guide me if i am wrong.
KaizenResultsInformationTable is MasterTable having field "recordinfo", this field contains Child table Ids as string.
kaizenResultsRecordInformationTable is Childtable having field "recordId".
I have to match records of child.
Query:
select recordinfo from KaizenResultsInformationTable
Output: ;0;1;2;3;4;5;6;7;8;9;10
Query:
select substr(replace(recordinfo,';','","'),3,length(recordinfo))
from KaizenResultsInformationTable`
Output: "0","1","2","3","4","5"
This query is not working:
select * from kaizenResultsRecordInformationTable
where substr(recordid,0,2) in (
select substr(replace(recordinfo,';','","'),3,length(recordinfo))
from KaizenResultsInformationTable
)
This query is working:
select * from kaizenResultsRecordInformationTable
where substr(recordid,0,2) in ("0","1","2","3","4","5")

You can't use in like that. In your second query, you are passing in a single string containing a comma-separated list of values.
It is better to represent a list of IDs as one record for each value.
Also, I'm not sure why you are taking a substring of your recordid. You should usually be storing one value per column.
However, if you can't change the schema, you can use string matching with 'like' instead of 'in'. Something like this should work:
select a.* from kaizenResultsRecordInformationTable a
join KaizenResultsInformationTable b
on (';'+b.recordinfo+';') LIKE ('%;'+trim(substr(recordid,0,2))+';%')
So if your recordinfo looks like 1;2;3;4;5;6, and your substr(recordid,0,2) looks like 1, this will include that row if ";1;2;3;4;5;6;" LIKE "%;1;%", which is true.

Related

How to concatenate a Select query inside a INSTR() in SQLite?

I was trying to order a result set by the order of the values in an IN() clause.
SELECT * FROM CrossReference WHERE cross_reference_id IN (SELECT Id FROM FilteredIds)
So I tried to find a function such as MySql FIELD(). Then I found these answers (answer1, answer2) which explain how to do the exact thing on SQLite using the INSTR().
SELECT *, INSTR(',GDBR10,GDBR5,GDBR30,', ',' || ticker || ',') POS
FROM tbl
WHERE POS>0
ORDER BY POS;
So it's working as expected, but I want to populate the ids dynamically using a select query. I tried many approaches, but nothing seemed to work. Here is the last one I tried. It gave me just one result row (a result related to the first filterId).
SELECT *, INSTR (','||(SELECT id FROM FilteredIds)||',', ',' || cross_reference_id || ',') POS FROM CrossReference WHERE POS>0 ORDER BY POS;
So I guess I'm making some kind of mistake when concatenating the SELECT query with the rest of the code. Because when I manually enter the filtered Ids it works and returns results according to the entered filter ids.

Aggregation Queries

Is it possible to do the following query in SQLite.Swift without resorting to arbitrary SQL (which I do have working but would prefer to avoid)?
select table1.id, sum(table1.col1*table2.col2)
from table1, table2
where table1.id=table2.id
group by table1.id
I've attempted the following: the SQL (through asSQL()) appears to be correct, but I can't find a way to reference the aggregate column from the returned row.
let query = table1.select(id, (table1[column1]*table2[column2]).sum
.join(table2, on: table1[id] == table2[id])
.group(id)
Can you alias columns somehow?
OK, I've found the solution, and it only took me 2 days!
The way to alias a column in SQLite.swift is to use an expression.
The name of the expression becomes the column alias.
So instead of
let query = table1.select(id, (table1[column1]*table2[column2]).sum)
.join(table2, on: table1[id] == table2[id])
.group(id)
Use:
let aggrColumn = (table1[column1]*table2[column2]).sum
let query = table1.select(id, aggrColumn)
.join(table2, on: table1[id] == table2[id])
.group(id)
let results = try db.prepare(query)
for row in results {
myAggrColumn = try row.get(aggrColumn)
}
Using
select id, sum(table1.col1*table2.col2)
from table1, table2
were table1.id=table2.id
group by id
Will result (see below for corrections) in 2 columns, namely id and sum(table1,col*table2.col2)
However both uses of id would be ambiguous as coded as there are two such source columns.
As such the query should be changed (see following code whihc assumes you want the id from table1 (shouldn't matter if table2 were used due to the join))
Additionally were is not a keyword, it should be WHERE
An alias would likely make things easier you make an alias using the AS keyword. The folloiwng also includes AS mysumcolumn thus the resultant columns will be id and mysumcolumn
select table1.id, sum(table1.col1*table2.col2) AS mysumcolumn
from table1, table2
where table1.id=table2.id
group by table1.id
Running this with no data results in :-

sqlite3, how can I look in all columns of an index in one time?

I have a table where 10 columns of it are used as tags (named TAG01, ..., TAG10). I made an index of these 10 columns.
so, if I want to fetch all rows with the word "happynewyear2015" in TAG01 I query this :
SELECT * FROM mytable INDEXED BY myindex WHERE TAG01=='happynewyear2015';
so, if "happynewyear2015" is in TAG02, or any other TAGXX but TAG01, the query above will not return the row. I'm looking for a query like :
SELECT * FROM mytable INDEXED BY myindex WHERE * =='happynewyear2015';
there is any way to do that?
A ten-column index would be useful only if you do searches on all the fields, like this:
... WHERE TAG01 = '...' AND TAG02 = '...' AND ...
You should store the tags in a separate table, with one row per tag, so that you get a query like this:
SELECT *
FROM MyTable
WHERE ID IN (SELECT MyTableID
FROM TagsTable
WHERE Tag = 'happynewyear2015')

Why do I get the error "Error: no such column: main.<tablename>.<columname>" although it exists?

This works:
sqlite> .databases
seq name file
--- --------------- ----------------------------------------------------------
0 main /path/to/db
2 uni /path/to/db
also this:
sqlite> pragma main.table_info(tsv_storage);
0|id|int|0||0
1|seqid|text|0||0
...
and this:
sqlite> select count(*) from main.tsv_storage;
198159
and also the attached database works:
sqlite> select * from uni.fasta_storage where uni.fasta_storage.id = 1;
1 MASNTVSAQ... Q197F8.1 002R_IIV3 Uncharacterized protein 002R Q197F8
but this not:
sqlite> select main.tsv_storage.seqid where main.tsv_storage.id=8;
Error: no such column: main.tsv_storage.seqid
EDIT:
and I have also problems with this, do I have to join the tables?
insert into main.tsv_storage(seqlength) select length(fasta) from
uni.fasta_storage where uni.fasta_storage.title = main.tsv_storage.seqid;
Error: no such column: main.tsv_storage.seqid
It happens for all columns, not only seqid. I think I did everything that is explained here: http://sqlite.awardspace.info/syntax/sqlitepg12.htm
What am I missing?
sqlite> select * from main.tsv_storage.seqid where main.tsv_storage.id=8;
You have not defined where to look for the selection. You need to tell the query what fields to search within the table, then define which table you are searching. The select * portion tells the query to look in all fields within the table. The from portion of the query tells the processes what table to look in. And lastly the where portion tells the query what to match when looking.
When using INSERT ... SELECT ..., the SELECT part must be valid query.
You cannot access a column like main.tsv_storage without having the table in the FROM clause:
INSERT INTO main.tsv_storage(seqlength)
SELECT length(fasta)
FROM uni.fasta_storage, main.tsv_storage
WHERE uni.fasta_storage.title = main.tsv_storage.seqid;
And the entire commands looks suspicious.
Are you sure you don't want to update the values in the seqlength column for existing records?
In that case, you would use something like this:
UPDATE main.tsv_storage
SET seqlength = (SELECT length(fasta)
FROM uni.fasta_storage
WHERE uni.fasta_storage.title = main.tsv_storage.seqid);

MySQL Changing Order Depending On Contents of a Column

I have a MySQL table Page with 2 columns: PageID and OrderByMethod.
I also then have a Data table with lots of columns including PageID (the Page the data is on), DataName, and DataDate.
I want OrderByMethod to have one of three entries: Most Recent Data First, Most Recent Data Last, and Alphabetically.
Is there a way for me to tack an "ORDER BY" clause to the end of this query that will vary its ordering method based on the contents of the "OrderByMethod" column? For example, in this query, I would want to have the ORDER BY clause contain whatever ordering rule is stored in Page 1's OrderByMethod column.
GET * FROM `Data` WHERE `Data`.`PageID`=1 ORDER BY xxxxxx;
Maybe a SELECT clause in the ORDER BY clause? I'm not sure how that would work though.
Thanks!
select Data.*
from Data
inner join Page on (Data.PageID=Page.PageID)
where Data.PageID=1
order by
if(Page.OrderByMethod='Most Recent Data First', now()-DataDate,
if(Page.OrderByMethod='Most Recent Data Last', DataDate-now(), DataName)
);
You can probably do this with the IF syntax to generate a column that you can then order by.
SELECT *, IF(Page.OrderBy = 'Alphabetically', Data.DataName, IF(Page.OrderBy = 'Most Recent Data First', NOW() - Data.DataDate, Data.DataDate - NOW())) AS OrderColumn
FROM Data
INNER JOIN Page ON Data.PageID = Page.PageID
WHERE Page.PageID = 1
ORDER BY OrderColumn
The direction of the ordering is determined in the calculation of the data instead of specifying a direction in the ORDER BY
Can you just append the order by clause to the select statement and rebind the table on postback?
If you want to use the content of the column in Page table as an expression in ORDER BY you have to do it using prepared statements. Let say, you store in OrderByMethod something like "field1 DESC, field2 ASC" and you want this string to be used as it is:
SET #order_by =(SELECT OrderByMethod FROM Page WHERE id = [value]);
SET #qr = CONCAT(your original query,' ORDER BY ', #order_by);
PREPARE stmt FROM #qr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
If you want the result set to be sorted based on the value of OrderByMethod , you can use IF as it was already mentioned by others, or CASE :
...
ORDER BY
CASE OrderByMethod
WHEN 'val1' THEN field_name1
WHEN 'val2' THEN field_name2
....etc
END

Resources