sqlite3 unable to select column from table in attached database - sqlite

I'm merging two similar databases (A and B) where I take entries in A that aren't in B and add them to B. I was trying to do it with an attached database (I used .open A.db and attach 'B.db' as B). Both have table C which contains column D. I need to do some inner joins on other tables, but first I need to do something like:
select D from C where not exists (select D from B.C where C.D = B.C.D);
And I get the error "no such column: B.C.D
Are you not allowed two dots in one expression? Do I need to somehow use "as" to fix that, or would that even work?

If the 2 tables contain a column D then you should not get that error.
But, there is another problem in the subquery:
select D from B.C where C.D = B.C.D
C.D is interpreted as the column D of the table B.C and not the table A.C as you might expect.
Set an alias for the table A.C and use it inside the subquery:
select D from C AS x where not exists (select D from B.C where x.D = B.C.D);
Or, use EXCEPT:
select D from C
EXCEPT
select D from B.C

Use quotes around those items that have dots in them
select D from C where not exists (select D from "B.C" where C.D = "B.C.D");
There is one question - where is the table "B" in your clause?

Related

Find rows with same non-null values

This seems like a rather straightforward problem, yet I have not been able to find the solution:
In a table test, I have some subset of columns which I am interested in, say a,b,c,d,e,f.
Some or most of these columns are NULL, but at least one is always filled.
Now for some rows, returned, say by:
SELECT rowid,a,b,c,d,e,f LIMIT 1;
I would like to get the number of rows which have the same non-null values.
So for example if a,d,f are the columns that are not NULL for this row, the result would be the same as for:
SELECT COUNT(*)
FROM test WHERE a=a_ AND d=d_ AND f=f_
SELECT a as a_, d as d_, f as f_ FROM test LIMIT 1;
How can this be done in one step / line? Or do I need a temporary table?
You can use the operator IS to compare safely values that may be NULL:
SELECT COUNT(*)
FROM test t1
INNER JOIN (SELECT a, b, c, d, e, f FROM test LIMIT 1) t2
ON (t1.a, t1.b, t1.c, t1.d, t1.e, t1.f) IS (t2.a, t2.b, t2.c, t2.d, t2.e, t2.f);
or with a CTE:
WITH cte AS (SELECT a, b, c, d, e, f FROM test LIMIT 1)
SELECT COUNT(*)
FROM test t1 INNER JOIN cte t2
ON (t1.a, t1.b, t1.c, t1.d, t1.e, t1.f) IS (t2.a, t2.b, t2.c, t2.d, t2.e, t2.f);
See the demo.

informix 11.5 How to count the number of members of a column separately

I have a table that have a column like this:
table1:
c1 c2 c3
. a .
. a .
. a .
a
b
b
c
How to get a result like the following?:
-- a b c
count(a) count(b) count(c)
Of course, there is an auxiliary table like the one below:
--field table
d1 d2
a
b
c
Transferring comments into an answer.
If there was an entry in table1.c2 with d as the value, is it correct to guess/assume that you'd want a fourth column of output with the name d and the count of the number of d values as the value. And there'd be an extra row in the auxilliary table too. That's pretty tricky.
You'd probably be better off with a result table with N rows, one for each value in the table1.c2 column, with the first column identifying the value and the second the count:
SELECT c2, COUNT(c2) FROM table1 GROUP BY c2 ORDER BY c2
To generate a single row with the names and counts as shown requires a dynamically built SQL statement — you write an SQL statement that generates the SQL (or the key components of the SQL) for a second statement that you actually execute to get the result. The main reason for it being dynamic like that is that the number of columns in the result set is not known until you run a query that determines which values exist in table1.c2. That's non-trivial — doable, but non-trivial.
I forget whether 11.50 has a built-in sysmaster:sysdual table. I ordinarily use a regular one-column, one-row table called dual. You can get the result you want, if your Table1.C2 has values a through e in it, with:
SELECT (SELECT COUNT(*) FROM Table1 WHERE c2 = 'a') AS a,
(SELECT COUNT(*) FROM Table1 WHERE c2 = 'b') AS b,
(SELECT COUNT(*) FROM Table1 WHERE c2 = 'c') AS c,
(SELECT COUNT(*) FROM Table1 WHERE c2 = 'd') AS d,
(SELECT COUNT(*) FROM Table1 WHERE c2 = 'e') AS e
FROM dual;
This gets the information you need. I don't think it is elegant, but "works" beats "doesn't work".

In SQLite, how can I delete rows in one table correspoding to the index in another table

I have two tables A and B. A contains whole data. B contains only the index that should be deleted. How can I delete the corresponding data in A that has the same index in B.
For example,
A is a table like:
B is a table like:
I should delete the rows in A with all the (x,y) pairs in B
and make A looks like this:
In MySQL (as the question was originally tagged) you can use join:
delete a
from a join
b
using (x, y);
In SQLite or almost any other database, you can use:
delete
from a
where exists (select 1 from b where b.x = a.x and b.y = a.y)
Thanks everyone. I have found a solution, something as below works for me in this question.
DELETE FROM a
WHERE EXISTS (SELECT *
FROM b
WHERE b.x = a.x and b.y = a.y)

SQLite How to Join to an extra Table

In this SQLite example, I am selecting rows from tables a, b, and c using the common column 'aa'.
SELECT
a.aa,
a.ab,
a.ac,
b.ba,
b.bb,
b.bc,
c.ca,
c.cb,
c.cc
FROM
a
INNER JOIN b ON b.ba = a.aa
INNER JOIN c ON c.ca = a.aa
WHERE a.ab = 'blahblah'
This works OK. Now, I need to add an extra table and an extra JOIN. Table 'd' has a column 'd.dc' that is common with table 'c' and its column 'c.cc'.
When the correct row is selected in 'c', I want to be able to read the data in 'd.dd'.
SELECT
a.aa,
a.ab,
a.ac,
b.ba,
b.bb,
b.bc,
c.ca,
c.cb,
c.cc,
d.dc,
d.dd
FROM
a
INNER JOIN b ON b.ba = a.aa
INNER JOIN c ON c.ca = a.aa
INNER JOIN d ON d.dc = c.cc
WHERE a.ab = 'blahblah'
This does not work OK. Please can you tell me how to correct it?
I have also tried
FOREIGN KEY (cc) REFERENCES d(dc)
in the table 'c' definition, but it makes no apparent difference.
Here are my table definitions:
CREATE TABLE `a` ( `aa` TEXT PRIMARY KEY UNIQUE, `ab` TEXT, `ac` TEXT );
CREATE TABLE `b` ( `ba` TEXT PRIMARY KEY UNIQUE, `bb` TEXT, `bc` TEXT );
CREATE TABLE `c` ( `ca` TEXT PRIMARY KEY UNIQUE, `cb` TEXT, `cc` TEXT, FOREIGN KEY (cc) REFERENCES d(dc) );
CREATE TABLE `d` ( `dc` TEXT PRIMARY KEY UNIQUE, `dd` TEXT );
The strange results that I got were rather hard to describe, but one thing I noticed was that the only few rows returned were where c.cc were all the same value, whereas in fact there should have many more rows, and c.cc should have had a variety of values.
Perhaps the following will explain how to JOIN using the SQL (but this is really just tailored to meet the rules):-
DROP TABLE IF EXISTS a;
DROP TABLE IF EXISTS b;
DROP TABLE IF EXISTS c;
DROP TABLE IF EXISTS d;
CREATE TABLE `a` ( `aa` TEXT PRIMARY KEY UNIQUE, `ab` TEXT, `ac` TEXT );
CREATE TABLE `b` ( `ba` TEXT PRIMARY KEY UNIQUE, `bb` TEXT, `bc` TEXT );
CREATE TABLE `c` ( `ca` TEXT PRIMARY KEY UNIQUE, `cb` TEXT, `cc` TEXT, FOREIGN KEY (cc) REFERENCES d(dc) );
CREATE TABLE `d` ( `dc` TEXT PRIMARY KEY UNIQUE, `dd` TEXT );
INSERT INTO d VALUES('blah_c_cc_001','blahblah_d_dd'); -- MUST BE INSERTED BEFORE C else FK CONFLICT
INSERT INTO a VALUES('blah_a_aa_001','blahblah','blahblah_a_ac');
INSERT INTO b VALUES('blah_a_aa_001','blahblah_b_bb','blahblah_b_bc');
INSERT INTO c VALUES('blah_a_aa_001','blahblah_c_cb','blah_c_cc_001');
INSERT INTO d VALUES('blah_c_cc_002','blahblah_d_dd'); -- MUST BE INSERTED BEFORE C else FK CONFLICT
INSERT INTO a VALUES('blah_a_aa_002','blahblah','blahblah_a_ac');
INSERT INTO b VALUES('blah_a_aa_002','blahblah_b_bb','blahblah_b_bc');
INSERT INTO c VALUES('blah_a_aa_002','blahblah_c_cb','blah_c_cc_002');
INSERT INTO d VALUES('blah_c_cc_004','blahblah_d_dd');
INSERT INTO a VALUES('blah_a_aa_003','blahblah','blahblah_a_ac');
INSERT INTO b VALUES('blah_a_aa_003','blahblah_b_bb','blahblah_b_bc');
INSERT INTO c VALUES('blah_a_aa_003','blahblah_c_cb','blah_c_cc_004');
SELECT *
FROM
a
INNER JOIN b ON b.ba = a.aa
INNER JOIN c ON c.ca = a.aa
INNER JOIN d ON d.dc = c.cc
WHERE a.ab = 'blahblah'
;
- * used for brevity
This results in :-
Basically the rule is that for a INNER (normal/simple) JOIN there must be matched rows, so in your query (the following applies)
TABLE b must have a value in column ba that matches the aa column in table a as well as the matching row in table a having a value of blahblah in column ab
AND
Table c must have a value in column ca that matches the aa column in table a as well as the matching row in table a having a value of blahblah
AND
Table d must have a value in column dc that matches the cc column in table c AND that the matching row in cc is a row that matches a row in table a that has a value of blahblah in column ab
The FOREIGN KEY has no impact on the SELECT query, other than it restricting the insertion of a row in table c in that the cc column being inserted must match the value of column dc in one of the rows in table d.
OK, I found my problem. The original code was OK, but the problem was in the external data that I was using. It wasn't matching because I had not bothered to TRIM it before loading it to my database.
My strange results occurred because if Table 'd' did not have a value in column dc that matches the cc column in table c, then no row at all was returned. I had assumed that if Table 'd' did not have a value in column dc that matches the cc column in table c, then the SELECT d.dd would just return an empty result, whereas in fact it blocked all output.
Message to Self: Always TRIM your data. Also, when monitoring results, always surround with quote-marks, so you can see the extra whitespace.

SQL query to select a view with a null column

I have table1 with columns A , B , C and another one, table2 with columns A, D.
I want to create a view to show columns A, B, C, D and there should be all values of column A even if there is no A in table2
I tried:
select
a, b, c, d
from
table 1
inner join
table 2 where table1.a = table2.a
suggest something
You will want to use an OUTER JOIN:
SELECT t1.a, t1.b, t1.c, t2.d
FROM table t1
LEFT JOIN table t2
ON t1.a = t2.a;

Resources