Why LEFT JOIN on LIKE statement gives different result on "_" changed to ","? - sqlite

table1:
code
category
ABC
ZMLND_XY_ABC
table2:
category
label
MLND
3
ZMLND
4
I'd like to map table1's category to table2's label if the part of table1's category separated by _ equals table2's category. For example, ZMLND_XY_ABC in table1 matches ZMLND in table2 while ZMLND_XY_ABC and MLND does not.
Query:
select * from table1 left join table2 on '_'||table1.category||'_' like '%_'||table2.category||'_%'
Result:
code | category | category_1 | label
ABC | ZMLND_XY_ABC | MLND | 3 <- _MLND_ should not match
_ZMLND_XY_ABC_
ABC | ZMLND_XY_ABC | ZMLND | 4
However, I replace _ by ,:
table1:
code
category
ABC
ZMLND,XY,ABC
select * from table1 left join table2 on ','||table1.category||',' like '%,'||table2.category||',%'
Result:
code
category
category_1
label
ABC
ZMLND,XY,ABC
ZMLND
4
Why are there different results?

Because of SQLITE like the _ is as special a character as the %.
As you seem to know, the % matches multiple characteres.
What you seem to have missed is that the _ matches any single character.
Compare e.g. https://www.sqlitetutorial.net/sqlite-like/
Have a look at https://www.sqlite.org/lang_expr.html concerning the ESCAPE optional syntax part, which probably can help you to write your query.

Related

Converting PL/SQL select rows in custom columns

I am stuck with this problem, I'm doing select like this:
select * from mytable;
and getting following results
-------------
|NAME |VALUE|
-------------
|nam1 |val1 |
-------------
|nam2 |val2 |
-------------
|nam3 |val3 |
-------------
Result is always formatted like this, NAME->VALUE.
Also, there are constraints placed on table so only one distinct NAME could appear in result. Also, values could be numbers, varchars, nulls, I don't want to do aggregation on this values.
Now I would like to convert this result to this:
--------------------
|NAM1 |NAM2 | NAM3 |
--------------------
|val1 |val2 | val3 |
--------------------
I tried achieving this result with pivot() function but without much success.
Thank you for your time, best regards :)
EDIT
This is the working example, with hardcoded column values, which is what I want to avoid.
select * from (select name, value from mytable)
pivot (min(value) for name in (
'nam1' as nam1
'nam2' as nam2
'nam3' as nam3
));
Using DECODE Function:
select name,
decode(name,'Name1','value1',0) as Name1,
decode(name,'Name2','value2',0) as Name2,
decode(name,'Name3','value3',0) as Name3,
decode(name,'Name4','value4',0) as Name4
from mytable
group by name
order by name;

Fastest way to generate a change set between 2 sql tables or CSV files

I am looking for a fast way to get the "deltas" between the 2 csv files (2 GB each).
(The CSV files are loaded to SQLite table where the CSV file first line are the column names, the 0th column is a unique key)
The output is supposed to be something along the lines of:
"Inserts" =... , "deletes" , "Updates" from new.csv to old.csv
The 0th column of the CSV can be considered unique
So something along the lines of:
File1:
id | c1 | c2 | c3 | ....
1 | v1 | v2 | v3 |
File2:
id | c1 | c2 | c3 | ....
1 | v1' | v2' | v3' |
When you have text files, the easiest way would be to sort them by their ID values (sort -n) and then use diff.
In SQL, you can get inserted and deleted rows by checking which IDs do not occur in the other table:
SELECT * FROM Table2 WHERE id NOT IN (SELECT id FROM Table1);
SELECT * FROM Table1 WHERE id NOT IN (SELECT id FROM Table2);
To get changed rows (here, with the new values), remove all identical rows with EXCEPT:
SELECT * FROM Table2
EXCEPT
SELECT * FROM Table1;

How to rank rows in a table in sqlite?

How can I create a column that has ranked the information of the table based on two or three keys?
For example, in this table the rank variable is based on Department and Name:
Dep | Name | Rank
----+------+------
1 | Jeff | 1
1 | Jeff | 2
1 | Paul | 1
2 | Nick | 1
2 | Nick | 2
I have found this solution but it's in SQL and I don't think it applies to my case as all information is in one table and the responses seem to SELECT and JOIN combine information from different tables.
Thank you in advance
You can count how many rows come before the current row in the current group:
UPDATE MyTable
SET Rank = (SELECT COUNT(*)
FROM MyTable AS T2
WHERE T2.Dep = MyTable.Dep
AND T2.Name = MyTable.Name
AND T2.rowid <= MyTable.rowid);
(The rowid column is used to differentiate between otherwise identical rows. Use the primary key, if you have one.)

selecting a row based on a number of column values in SQLite

I have a table with this structure:
id | IDs | Name | Type
1 | 10 | A | 1
2 | 11 | B | 1
3 | 12 | C | 2
4 | 13 | D | 3
except id nothing else is a FOREIGN or PRIMARY KEY. I want to select a row based on it's column values that are not PRIMARY KEY. I have tried the following syntax but it yields no results.
SELECT * FROM MyTable WHERE Name = 'A', Type = 1;
what am I doing wrong? What is exactly returned by a SELECT statement? I'm totally new to Data Base and I'm currently experimenting and trying to learn it. so far my search has not yield any results regarding this case.
Use and to add multiple conditions to your query
SELECT *
FROM MyTable
WHERE Name = 'A'
AND Type = 1;

UPDATE multiple rows using SELECT

I have A table and two rows with id=1 and id=2 and their x parameter is 1. I also have B table and two rows with same id 1 and 2. I am trying to update all of the data(column)on B table which has same id with A table whose x parameter is 1.
A table
id | x |
1 | 1 |
2 | 1 |
B table
id | Y |
1 | yes|
2 | yes|
My query is
UPDATE B SET y='No' WHERE B.id=(SELECT A.id FROM A WHERE A.x=1);
The problem is select returns mutliple data and i can only update the first data.
I tried to use JOIN but sqlite gives syntax error near INNER i couldn't find the problem.
UPDATE B SET B.y='No' INNER JOIN A ON B.id=A.id WHERE A.x=1;
Use this:
UPDATE ... WHERE B.id IN (SELECT A.id ...);

Resources