[sqlite] I don't understand how to use NOT EXISTS

2015-09-20 Thread Simon Slavin

On 20 Sep 2015, at 7:15pm, James K. Lowden  wrote:

> Simon Slavin  wrote:
> 
>> Constructions like this
>> 
>>> INSERT INTO _TAG_EXISTS_RESULT_ ( NAME, BOOL )
>>> SELECT 'evil little sister'
>> 
>> should be rewritten so that you are not trying to do a SELECT in the
>> middle of your INSERT.
> 
> Why in the world would you say that?  That's the SQL assignment
> function, the equivalent of 
> 
>   A = A + B

I would argue that that would be UPDATE, not INSERT.  But I see your side of 
the issue.

> Anything you'd do to rewrite it would result in something more complex,
> doubly so if it included the atomicity guarantee of the original. 

Suppose the SELECT doesn't return anything.  Do you still want to do the INSERT 
? Do you now have to look up the values to INSERT elsewhere ?  Put the commands 
in a transaction if that worries you.

You're right -- I should probably have written "I preffer" instead if making it 
an absolute statement.

Simon.


[sqlite] I don't understand how to use NOT EXISTS

2015-09-20 Thread James K. Lowden
On Sun, 20 Sep 2015 19:33:35 +0100
Simon Slavin  wrote:

> On 20 Sep 2015, at 7:15pm, James K. Lowden 
> wrote:
> 
> > Simon Slavin  wrote:
> > 
> >> Constructions like this
> >> 
> >>> INSERT INTO _TAG_EXISTS_RESULT_ ( NAME, BOOL )
> >>> SELECT 'evil little sister'
> >> 
> >> should be rewritten so that you are not trying to do a SELECT in
> >> the middle of your INSERT.
> > 
> > Why in the world would you say that?  That's the SQL assignment
> > function, the equivalent of 
> > 
> > A = A + B
> 
> I would argue that that would be UPDATE, not INSERT.  But I see your
> side of the issue.

I actually think that's the crux of the matter, Simon.  If you think
you're operating on a row, then A = A + B is UPDATE, yes.  If you think
you're operating on tables, then A = A + B is INSERT, and UPDATE
is more like 

A = (A - C) + B

where C is the set of rows being replaced by B. 

> Suppose the SELECT doesn't return anything.  Do you still want to do
> the INSERT ? 

If I said WHERE NOT EXISTS, why would I still want to "do the insert"?!
I'm with Yoda here: there is no try.  

> Do you now have to look up the values to INSERT elsewhere ?

No, I do not, not if the values I didn't insert can be specified, e.g.

insert into S 
select * from T where exists 
(select 1 from R where ... );

If the values can't be specified in like manner, that would suggest to
me a problem with the database design.  

TIMTOWTDI, for sure.  More than one way to think about it, too.  But I
see no downside to using INSERT...SELECT, except that it's startling to
someone unfamiliar with it.  

--jkl


[sqlite] I don't understand how to use NOT EXISTS

2015-09-20 Thread James K. Lowden
On Wed, 16 Sep 2015 08:23:04 +1000
Barry Smith  wrote:

> As for your original query: think about just the select clause (you
> can run it independently). This will return ('magnetohydrodynamics',
> 1) for each row in the table. 

It took me a bit to understand what you meant.  I also think there's a
better answer than resorting to LIMIT 1.  

To clarify, the OP's query is (reformatted):

> INSERT INTO TAGS ( NAME, COUNT ) 
> SELECT 'magnetohydrodynamics', 1
> FROM TAGS -- <- the error 
> WHERE NOT EXISTS (
>   SELECT * FROM TAGS 
>   WHERE NAME = 'magnetohydrodynamics' 
> );

The existence test is against the whole TAGS table.  As long as the
name 'magnetohydrodynamics' appears in the table, SELECT will return
zero rows.  But -- your point -- if the name tested does *not* appear in
the table, SELECT will return as many rows as are in the table.  

The solution is simply to say what's meant instead: 

INSERT INTO TAGS ( NAME, COUNT ) 
SELECT 'magnetohydrodynamics',1 
WHERE NOT EXISTS (
SELECT 1 FROM TAGS 
WHERE NAME = 'magnetohydrodynamics' 
);

As to the OP's question about where he went wrong, the query as
presented should not have created the results he showed.  Those results
could be explained, though, if "magnetohydrodynamics" was misspelled in
the WHERE clause.  I suspect that's what went wrong.  

--jkl


[sqlite] I don't understand how to use NOT EXISTS

2015-09-20 Thread James K. Lowden
On Wed, 16 Sep 2015 19:40:23 +0100
Simon Slavin  wrote:

> Constructions like this
> 
> > INSERT INTO _TAG_EXISTS_RESULT_ ( NAME, BOOL )
> > SELECT 'evil little sister'
> 
> should be rewritten so that you are not trying to do a SELECT in the
> middle of your INSERT.

Why in the world would you say that?  That's the SQL assignment
function, the equivalent of 

A = A + B

Anything you'd do to rewrite it would result in something more complex,
doubly so if it included the atomicity guarantee of the original.  

--jkl



[sqlite] I don't understand how to use NOT EXISTS

2015-09-18 Thread R.Smith


On 2015-09-18 03:13 AM, Keith Medcalf wrote:
>> Some initial things.
>
>> Data needs to be kept in 1NF (or 1st-Normal-Form) which is relational
>> theory speak for "Everything without a 1-to-1 relationship with the key
>> field in a table, should be in another table".  Many reasons for this
>> (if you care to read up on some RT) but the most simple reason is: We
>> can make complex extractions from 1NF data tables via JOINs, sub-queries
>> and the like, but we cannot extract simple information (or de-complicate
>> it) from convoluted tables.
> Except for very simple cases, data in first normal form that is not also in 
> third or boyce-codd normal form usually has anomalous update/delete 
> behaviour.  Although it may be complicated, one usually wants to normalize to 
> at least third normal.  Then you can denormalize (usually for performance 
> reasons) and deal with the anomalies that you (re)introduce through each 
> denormalization step manually.

Indeed, and thank you for adding that. I seem to recall someone on this 
forum quoting an old adage long ago re this - something to the effect of:
"Normalize until it hurts; denormalize until it works."


(As long as we avoid Knuth's root of all evil: Premature optimization.)
Ryan



[sqlite] I don't understand how to use NOT EXISTS

2015-09-17 Thread R.Smith


On 2015-09-17 05:13 AM, Nicolas J?ger wrote:
> @Ryan,
>> To get you started on this road, may I ask you take a leap of faith
>> and explain to us from A to Z what you would like to achieve with the
>> tables and data you are asking about above - i.e don't show us the
>> programming you think will solve the problem and ask us if that is
>> good SQL, rather explain us the problem to be solved and allow us to
>> show you the good SQL that will do it.
>>
>> Every next task should be clearer and easier.
> Actualy, it's a personal open source project. So the code could be see
> by anyone. The only thing is, the most recent part isn't yet on the
> repo (last push was before the summer). But, if for some reason you
> want to see the code as it is today on my computer (almost all files
> were heavily modified during the summer), I can push it.
>
> this project is about helping me to manage all files I have on my
> computer. I'm a metalhead and science nerd at the same time.
> So, I have tons of music and tons of ebooks and publications... So my
> project as currently two goals:
>
>1) store the data on disk, I should not access the files directly.
>
>2) using a DB to retrieve any document trough a search engine.
>
> (actually I want to add a third goal: I want to create something I
> don't know how I will call it, but it's something like a binder. For
> example if you open a binder about 'modelling demons', you can link data
> of differents files even if they don't share tags or whatever (can be
> in that example some texture, some .blend or pdf about modelling
> humanoid...).)
>
> So, I'm writing some custom GTKmm widgets wich interact with the DB
> (but they don't directly access any sqlite function, I'm working with
> engines communication (gtkmm_engine, sqlite_engine, etc.)).
>
> I'm currently thinking to make that program modular. For example, the
> user (usualy me), set what kind of data (trough some config file (in
> my head I call these files 'collection')) should be store in the
> DB. For each data will correspond a widget.
>
> Let's took an example,
>
> for ebooks:
>
> I want to save the filename (filename is ruled by the program, the
> user has no direct way to modify it), title, some tags and a description
> for each ebook (for the last three the program shows some widgets,
> wich allow the user to modify the values).
>
> At this point, when the program read the ebook.collection, it will
> create a first table EBOOK with four columns
> (ID,FILENAME,TITLE,DESCRIPTION)
>
> for the tags, things are more complicated. I need two tables:
> - TAGS with three columns (ID,NAME,COUNT)
> - TAGSMAP with two columns (ID_EBOOK,ID_TAGS) (I explain the use below)
>
> so if I take my old example :
>
> (id|NAME|COUNT)
> 53|black metal|3
> 55|occult rock|3
> 61|satanic smurfs|1
> 62|beer|0
> 63|pizza|0
>
> if I'm seeking to get all files with the tags 'black metal' the program
> check all entries in TAGSMAP with ID_TAGS = 53,
>
> SELECT * FROM TAGSMAP WHERE ID_TAGS = 53 would returns something like,
>
> (ID_EBOOK|ID_TAGS)
> 3|53
> 5|53
> 9|53
>
> then the ID_EBOOKs refer to the IDs of the data (title and description
> in this case) for some files in EBOOK.
>
> now my problems come when you want to add/delete a tags. If for a file
> you want (eg) to delete the tag 'black metal' you click on the button I
> setup to delete that tag, the program at this time has two
> informations:
>
> the current EBOOK.FILENAME and the TAGS.NAME of the tag.
>
> So I have to query the DB to get their respective IDs (ID of that
> FILENAME in EBOOK and ID of that NAME in TAGS).
>
> Then, the program has to delete the entry in the TAGSMAP where ID_EBOOK
> is the same than ID for the current file in EBOOK and where ID_TAGS
> equal the ID in TAGS.
>
> For TAGS, the program has first to check COUNT. Before the check I have
> to get the value from the DB.
>
>If COUNT = 1, the program has to delete the tag with NAME 'black
>metal'.
>
>If COUNT > 1, the program has to decrement count.
>
> My first manner to do that, was to just store/read the data to/from the
> DB. All conditions (like what I try to do for some days now...) were
> executed by the program, not by queries. But the problem (wich is
> not really a big issue), I do a lot of queries because of the IFs in my
> program then I get one/two seconds of lags (wich may also be here
> because I wrote all operation I do in the console for debug
> purpose...)...
>
> So, as I wrote in an earlier email, since I know I can use
> transaction, I try to replace all queries in one giant query send to
> the DB when I want to update the data for a file (title, tags and
> description).
>
> Maybe, I should ask if what I want to do is really possible by
> SQL or if I should better let the IFs in the program better than
> struggling like I did in my last emails...
>
>
> I really hope I was clear. If you need further explanation about
> something just tell it. Anyway thank you for the time you 

[sqlite] I don't understand how to use NOT EXISTS

2015-09-17 Thread Keith Medcalf
> Some initial things.


> Data needs to be kept in 1NF (or 1st-Normal-Form) which is relational
> theory speak for "Everything without a 1-to-1 relationship with the key
> field in a table, should be in another table".  Many reasons for this
> (if you care to read up on some RT) but the most simple reason is: We
> can make complex extractions from 1NF data tables via JOINs, sub-queries
> and the like, but we cannot extract simple information (or de-complicate
> it) from convoluted tables.

Except for very simple cases, data in first normal form that is not also in 
third or boyce-codd normal form usually has anomalous update/delete behaviour.  
Although it may be complicated, one usually wants to normalize to at least 
third normal.  Then you can denormalize (usually for performance reasons) and 
deal with the anomalies that you (re)introduce through each denormalization 
step manually.







[sqlite] I don't understand how to use NOT EXISTS

2015-09-17 Thread R.Smith


On 2015-09-16 08:27 PM, Nicolas J?ger wrote:
> Hi guys,
>
> so there is the two ways I made:
>
> FIRST ONE:
> ==
>
> ** Create a table wich will store the result of EXISTS,
>
> CREATE TABLE _TAG_EXISTS_RESULT_( NAME, BOOL );
>
>
> ** The next query has to INSERT 'evil little sister' with BOOL to 1 in
> _TAG_EXISTS_RESULT_ if 'evil little sister' is already present in TAGS,
>
> INSERT INTO _TAG_EXISTS_RESULT_ ( NAME, BOOL )
> SELECT 'evil little sister'
> , EXISTS (SELECT 1 FROM TAGS WHERE NAME='evil little sister');
>
>
> ** Then I add 'evil little sister' if _TAG_EXISTS_RESULT_.BOOL = 0..
>
> INSERT INTO TAGS (NAME, COUNT)
>VALUES(
>  CASE ( SElECT BOOL FROM _TAG_EXISTS_RESULT_ ) WHEN 0
>THEN ( SElECT NAME FROM _TAG_EXISTS_RESULT_ )
>ELSE '$NOT_USED$'
>  END
>, 0 );
>
> ** delete $NOT_USED$ if so,
>
> DELETE FROM TAGS WHERE NAME='$NOT_USED$';
>
>
> ** Then, clear _TAG_EXISTS_RESULT_,
>
> DELETE FROM  _TAG_EXISTS_RESULT_;
>
>
> SECOND ONE:
> ==
>
> ** I made a compact version,
>
> INSERT INTO TAGS (NAME, COUNT)
>VALUES
>(
>  CASE( SELECT EXISTS( SELECT 1 FROM TAGS WHERE NAME='evil little
> sister' ) ) WHEN 0
>  THEN 'evil little sister'
>  ELSE '$NOT_USED$'
>  END
>, 1
>);
>
>
> ** delete $NOT_USED$ if so,
>
> DELETE FROM TAGS WHERE NAME='$NOT_USED$';
>
>
> comments are welcome.

It's hard to know where to begin. This looks much more like programming 
code than SQL - and while there are similarities, the usage is very 
different.

Let me start with explaining the first and most important difference:
Most programming languages are imperative (methodical or executive) 
descriptors - i.e you tell the process/engine/compiler HOW to achieve a 
task (which seems a bit like what you are trying to do up above).
SQL is really a declarative language, i.e. you tell the process/engine 
WHAT you need, and it will figure out HOW to achieve that in the best 
and most efficient way.

Of course, that is easier said than done, but we've all started with 
little things and built on from there. Very soon you will see how you 
can create a schema and some queries to achieve data-handling tasks that 
used to take you ages to program (at least, that's how it happened for me).

To get you started on this road, may I ask you take a leap of faith and 
explain to us from A to Z what you would like to achieve with the tables 
and data you are asking about above - i.e don't show us the programming 
you think will solve the problem and ask us if that is good SQL, rather 
explain us the problem to be solved and allow us to show you the good 
SQL that will do it.

Every next task should be clearer and easier.

Cheers,
Ryan



[sqlite] I don't understand how to use NOT EXISTS

2015-09-17 Thread Nicolas Jäger
Hi,

@Simon,

> >CASE ( SElECT BOOL FROM _TAG_EXISTS_RESULT_ ) WHEN 0
> 
> CASE takes a value.  You can't put a SQLite command in there.
> 
actually, it's working if you put the command between (). I guess it's
like the `` on linux (eg),

mplayer `ls *.mp3`

but maybe,even if it's working, you want to point that's not correct to
use it.

> More generally, you come from a programming background and are
> expecting SQL to work like a programming language.  It doesn't.

that's clearly a difficulty for me...

> Constructions like this
> 
> > INSERT INTO _TAG_EXISTS_RESULT_ ( NAME, BOOL )
> > SELECT 'evil little sister'
> 
> should be rewritten so that you are not trying to do a SELECT in the
> middle of your INSERT.
> 
> This is why we quoted the form
> 
> INSERT OR IGNORE ...;
> UPDATE ...;
> 
> earlier.  Two separate commands, not one command trying to run
> another.

I have to think about that...

-

@Ryan,

> To get you started on this road, may I ask you take a leap of faith
> and explain to us from A to Z what you would like to achieve with the
> tables and data you are asking about above - i.e don't show us the
> programming you think will solve the problem and ask us if that is
> good SQL, rather explain us the problem to be solved and allow us to
> show you the good SQL that will do it.
> 
> Every next task should be clearer and easier.

Actualy, it's a personal open source project. So the code could be see
by anyone. The only thing is, the most recent part isn't yet on the
repo (last push was before the summer). But, if for some reason you
want to see the code as it is today on my computer (almost all files
were heavily modified during the summer), I can push it.

this project is about helping me to manage all files I have on my
computer. I'm a metalhead and science nerd at the same time.
So, I have tons of music and tons of ebooks and publications... So my
project as currently two goals:

  1) store the data on disk, I should not access the files directly.

  2) using a DB to retrieve any document trough a search engine.

(actually I want to add a third goal: I want to create something I
don't know how I will call it, but it's something like a binder. For
example if you open a binder about 'modelling demons', you can link data
of differents files even if they don't share tags or whatever (can be
in that example some texture, some .blend or pdf about modelling
humanoid...).)

So, I'm writing some custom GTKmm widgets wich interact with the DB
(but they don't directly access any sqlite function, I'm working with
engines communication (gtkmm_engine, sqlite_engine, etc.)).

I'm currently thinking to make that program modular. For example, the
user (usualy me), set what kind of data (trough some config file (in
my head I call these files 'collection')) should be store in the
DB. For each data will correspond a widget.

Let's took an example,

for ebooks:

I want to save the filename (filename is ruled by the program, the
user has no direct way to modify it), title, some tags and a description
for each ebook (for the last three the program shows some widgets,
wich allow the user to modify the values).

At this point, when the program read the ebook.collection, it will
create a first table EBOOK with four columns
(ID,FILENAME,TITLE,DESCRIPTION)

for the tags, things are more complicated. I need two tables: 
- TAGS with three columns (ID,NAME,COUNT)
- TAGSMAP with two columns (ID_EBOOK,ID_TAGS) (I explain the use below)

so if I take my old example :

(id|NAME|COUNT)
53|black metal|3
55|occult rock|3
61|satanic smurfs|1
62|beer|0
63|pizza|0

if I'm seeking to get all files with the tags 'black metal' the program
check all entries in TAGSMAP with ID_TAGS = 53,

SELECT * FROM TAGSMAP WHERE ID_TAGS = 53 would returns something like,

(ID_EBOOK|ID_TAGS)
3|53
5|53
9|53

then the ID_EBOOKs refer to the IDs of the data (title and description
in this case) for some files in EBOOK.

now my problems come when you want to add/delete a tags. If for a file
you want (eg) to delete the tag 'black metal' you click on the button I
setup to delete that tag, the program at this time has two
informations:

the current EBOOK.FILENAME and the TAGS.NAME of the tag.

So I have to query the DB to get their respective IDs (ID of that
FILENAME in EBOOK and ID of that NAME in TAGS).

Then, the program has to delete the entry in the TAGSMAP where ID_EBOOK
is the same than ID for the current file in EBOOK and where ID_TAGS
equal the ID in TAGS.

For TAGS, the program has first to check COUNT. Before the check I have
to get the value from the DB.

  If COUNT = 1, the program has to delete the tag with NAME 'black
  metal'.

  If COUNT > 1, the program has to decrement count.

My first manner to do that, was to just store/read the data to/from the
DB. All conditions (like what I try to do for some days now...) were
executed by the program, not by queries. But the problem 

[sqlite] I don't understand how to use NOT EXISTS

2015-09-16 Thread Keith Medcalf

> @Simon,
> 
> > >CASE ( SElECT BOOL FROM _TAG_EXISTS_RESULT_ ) WHEN 0
> >
> > CASE takes a value.  You can't put a SQLite command in there.
> >
> actually, it's working if you put the command between (). I guess it's
> like the `` on linux (eg),
> 
> mplayer `ls *.mp3`
> 
> but maybe,even if it's working, you want to point that's not correct to
> use it.

It is fine to use it that way.  A Select inside parenthesis is a "scalar 
subselect".  It will return a single value (in this case BOOL) from the first 
row returned by the select statement.  It is perfectly valid.







[sqlite] I don't understand how to use NOT EXISTS

2015-09-16 Thread Simon Slavin

On 16 Sep 2015, at 7:27pm, Nicolas J?ger  wrote:

>CASE ( SElECT BOOL FROM _TAG_EXISTS_RESULT_ ) WHEN 0

CASE takes a value.  You can't put a SQLite command in there.

More generally, you come from a programming background and are expecting SQL to 
work like a programming language.  It doesn't.  Constructions like this

> INSERT INTO _TAG_EXISTS_RESULT_ ( NAME, BOOL )
> SELECT 'evil little sister'

should be rewritten so that you are not trying to do a SELECT in the middle of 
your INSERT.

This is why we quoted the form

INSERT OR IGNORE ...;
UPDATE ...;

earlier.  Two separate commands, not one command trying to run another.

Simon.


[sqlite] I don't understand how to use NOT EXISTS

2015-09-16 Thread Nicolas Jäger
Hi guys,

so there is the two ways I made:

FIRST ONE:
==

** Create a table wich will store the result of EXISTS,

CREATE TABLE _TAG_EXISTS_RESULT_( NAME, BOOL );


** The next query has to INSERT 'evil little sister' with BOOL to 1 in
_TAG_EXISTS_RESULT_ if 'evil little sister' is already present in TAGS,

INSERT INTO _TAG_EXISTS_RESULT_ ( NAME, BOOL )
SELECT 'evil little sister'
, EXISTS (SELECT 1 FROM TAGS WHERE NAME='evil little sister');


** Then I add 'evil little sister' if _TAG_EXISTS_RESULT_.BOOL = 0..

INSERT INTO TAGS (NAME, COUNT)
  VALUES(
CASE ( SElECT BOOL FROM _TAG_EXISTS_RESULT_ ) WHEN 0
  THEN ( SElECT NAME FROM _TAG_EXISTS_RESULT_ )
  ELSE '$NOT_USED$'
END
  , 0 );

** delete $NOT_USED$ if so,

DELETE FROM TAGS WHERE NAME='$NOT_USED$';


** Then, clear _TAG_EXISTS_RESULT_,

DELETE FROM  _TAG_EXISTS_RESULT_;


SECOND ONE:
==

** I made a compact version,

INSERT INTO TAGS (NAME, COUNT)
  VALUES 
  (
CASE( SELECT EXISTS( SELECT 1 FROM TAGS WHERE NAME='evil little
sister' ) ) WHEN 0
THEN 'evil little sister'
ELSE '$NOT_USED$'
END
  , 1 
  );


** delete $NOT_USED$ if so,

DELETE FROM TAGS WHERE NAME='$NOT_USED$';


comments are welcome.



Of course, as I wrote yesterday, if UNIQUE can help to do the job
faster, I'll go with it. But this problem show me I do not realy well
understand how I have to think when I write a SQL statement. In C you
can do something like,

IF (condition) THEN (doSomething) END

in SQL, it appears to me now, I can't think like this. So I have a
question what are the words (like SELECT/UPDATE/INSERT) allowed to
start a query ?

regards,
Nicolas J.


[sqlite] I don't understand how to use NOT EXISTS

2015-09-16 Thread Barry Smith
If you have a unique index on name, you could use INSERT OR IGNORE. 
https://www.sqlite.org/lang_conflict.html

INSERT OR IGNORE INTO TAGS (NAME, COUNT) VALUES ('Bleh', 1)

As for your original query: think about just the select clause (you can run it 
independently). This will return ('magnetohydrodynamics', 1) for each row in 
the table. 

If you did not want to use INSERT OR IGNORE, you could put a LIMIT 1 in there, 
or rephrase your query to not use TAGS in the outer select (note: you never 
actually reference anything in the TAGS specified in the outer select)

> On 15 Sep 2015, at 1:06 pm, Nicolas J?ger  
> wrote:
> 
> hi,
> I have a table TAGS with idkey and two colums (NAME, COUNT):
> 
> id|NAME|COUNT
> 53|black metal|3
> 55|occult rock|3
> 61|satanic smurfs|1
> 62|beer|0
> 63|pizza|0
> 
> I want to check if some tag exist by checking if `NAME` is recorded
> in the table or not. If not, I want to add it;
> 
> INSERT INTO TAGS ( NAME, COUNT ) SELECT 'magnetohydrodynamics', 1
> FROM TAGS WHERE NOT EXISTS (SELECT * FROM TAGS WHERE NAME =
> 'magnetohydrodynamics' );
> 
> then if I look up in the table I see:
> 
> id|NAME|COUNT
> 53|black metal|3
> 55|occult rock|3
> 61|satanic smurfs|1
> 62|beer|0
> 63|pizza|0
> 64|magnetohydrodynamics|1
> 65|magnetohydrodynamics|1
> 66|magnetohydrodynamics|1
> 67|magnetohydrodynamics|1
> 68|magnetohydrodynamics|1
> 
> could you tell me please where I did some mess ?
> 
> regards,
> Nicolas J.
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users


[sqlite] I don't understand how to use NOT EXISTS

2015-09-15 Thread R.Smith


On 2015-09-15 06:01 PM, Nicolas J?ger wrote:
> hi Keith, hi others,
>
>> If there should only be one entry for each name (and it is not case
>> sensitive),
> I'm using sqlite trough a C++ program wich take care of the case
> sensitive. In this very case, each entry has to be unique.

Fine, but do think of if you ever might want to use the DB via anything 
else, or a DB admin program... best is to ensure the DB schema itself 
knows the collation and case sensitivity requirements.

>
>> your best bet would be to declare that NAME is unique:
>>
>> create table Tags
>> (
>>id integer primary key,
>>name text collate nocase unique,
>>count integer not null
>> );
>>
>> Then when you want to insert you just do so, as in:
>>
>> INSERT OR IGNORE INTO TAGS (name, count) VALUES
>> ('magnetohydrodynamics', 0);
>>
>> To increment a count you would do:
>>
>> INSERT OR IGNORE INTO TAGS (name, count) VALUES
>> ('magnetohydrodynamics', 0); UPDATE TAGS SET count = count + 1 WHERE
>> name = 'magnetohydrodynamics';
> that's definitely something I want do! thanx!
>
> but I also would like to know how can I check if an entry exists,(or not
> exists), in a table. Like,
>
> IF (exists) THEN (doSomething) END
>
> even if the same entry is present several times I want to execute
> `doSomething` only one time.

That IF..THEN is not SQL so won't ever work. (I know MSSQL allows that 
in the TSQL, but that is not an SQL or SQLite thing).

Making the EXISTS work is more easy:

To demonstrate a normal use of EXISTS - this query script is a sort of 
merge, it scans a table and then INSERTS the stuff into another table if 
it doesn't exist yet, or updates it if it does exist:

-- Make a CTE full of only the items in t1 that already exists in t2...
-- then update column b (in this case) for all of those.
WITH upd(id, a, b, c) AS (
   SELECT id, a, b, c FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE
t2.id = t1.id)
)
UPDATE t2 SET t2.b = (SELECT upd.b FROM upd WHERE upd.id=t2.id)
WHERE t2.id IN (SELECT upd.id FROM upd);

-- Make a CTE full of only the items in t1 that does not exist yet
in t2...
-- then add them
WITH ins(id, a, b, c) AS (
   SELECT id, a, b, c FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2
WHERE t2.id = t1.id)
)
INSERT INTO t2(id, a, b, c) SELECT id, a, b, c FROM ins;



(Note: We do the update before the insert to simply avoid updating newly 
inserted things, but it will work either way round).


Another common use is adding items to a query based on whether or not 
they appear in a completely different table, and there is no need to 
otherwise JOIN that table to the current query, like this:

-- Say we want to see all the items in t1 that are also found in t2...
SELECT id, a, b, c FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE
t2.id = t1.id);

-- That can of course easily be achieved with a join too, like this:
SELECT id, a, b, c
FROM t1
   LEFT JOIN t2 ON t2.id=t1.id
WHERE t2.id IS NOT NULL


It is in fact hard to fathom a simple query where EXISTS is the only 
possible solution (i.e. the answer cannot be achieved with a simple 
JOIN  or WHERE clause addition) which is why Keith said "your best bet 
is to..." and then demonstrated a way without using EXISTS.

btw: The whole SELECT 1 WHERE   does not have to be 1, you can as 
easily select anything in the table, such as id, but since the EXISTS 
clause do not care WHAT is selected, it simply sees if ANY rows are 
returned, we usually just put a 1 to avoid any wasted cpu cycles.


HTH,
Ryan



[sqlite] I don't understand how to use NOT EXISTS

2015-09-15 Thread Nicolas Jäger
Hi people!



@Ryan,

> Fine, but do think of if you ever might want to use the DB via
> anything else, or a DB admin program... best is to ensure the DB
> schema itself knows the collation and case sensitivity requirements.

I have to take care of the case sensitivity through the interface of my
program, but I will also consider your comment.

> It is in fact hard to fathom a simple query where EXISTS is the only 
> possible solution (i.e. the answer cannot be achieved with a simple 
> JOIN  or WHERE clause addition) which is why Keith said "your best
> bet is to..." and then demonstrated a way without using EXISTS.

in my present problem, I can use `unique`. I'm not at home know, but I
definitely have to play a little with your solutions.



@Simon,

> you can submit this query and know that there is definitely an answer
> which is definitely a floating point value.  And then in your
> programming language you can do your equivalent of
>
> IF (theanswer) > 0.0 THEN (doSomething) END

actualy I do that in C++,

if ( getTagCount( name ) == 0 ) // `0` means not present in the table
{
transaction.Add("INSERT INTO TAGS (NAME, COUNT) VALUES ('"+name+"',
0 );"); 
}

with `getTagCount()`, a function wich ask the db:

SELECT COUNT FROM TAG WHERE NAME = 'biology';

so if I got nothing from the query, `getTagCount()` returns 0 by itself
otherwise I convert the result given by the query to an integer.

but now, I try to merge all queries in one query since I heard about
`transactions`.



@Igor,

> > sqlite> select count(a) from x;
> 
> Better still:
> 
> select exists (select 1 from x);
> 
> The difference is that the version with count() always scans the
> whole table, while the latter stops at the first record - which is
> good enough if you only need to check for existence, and don't
> actually need the count.

that's a good stuff.

I will think a little, to store the result of some query like,

select exists (select 1 from Tags WHERE name='magnetohydrodynamics');

then using a case over that result...

CASE result WHEN 0 THEN addMe ELSE doNotAddMe END

 I have to try, I never used case in Sqlite so far...



thank you guys!

regards,
Nicolas


[sqlite] I don't understand how to use NOT EXISTS

2015-09-15 Thread Simon Slavin

On 15 Sep 2015, at 5:01pm, Nicolas J?ger  wrote:

> I also would like to know how can I check if an entry exists,(or not
> exists), in a table. Like,
> 
> IF (exists) THEN (doSomething) END

Here's another alternative to add to those in Ryan's excellent post.  With your 
schema

> create table Tags
> (
>  id integer primary key,
>  name text collate nocase unique,
>  count integer not null
> );

You can do things like

SELECT total(count) FROM Tags WHERE id=234;
SELECT total(count) FROM Tags WHERE name='biology';

You will definitely get a reply from this since 'total()' returns 0.0 even if 
there are no rows which satisfy the WHERE clause.

So you can submit this query and know that there is definitely an answer which 
is definitely a floating point value.  And then in your programming language 
you can do your equivalent of

IF (theanswer) > 0.0 THEN (doSomething) END

Warning: although SQLite also has the function sum() it does not produce the 
same result to total() when no lines satisfy the WHERE clause.  Sorting out the 
possibilities is more complicated.

Simon.


[sqlite] I don't understand how to use NOT EXISTS

2015-09-15 Thread Igor Tandetnik
On 9/15/2015 2:04 PM, John McKown wrote:
> sqlite> select count(a) from x;

Better still:

select exists (select 1 from x);

The difference is that the version with count() always scans the whole 
table, while the latter stops at the first record - which is good enough 
if you only need to check for existence, and don't actually need the count.
-- 
Igor Tandetnik



[sqlite] I don't understand how to use NOT EXISTS

2015-09-15 Thread John McKown
Very good! I'll keep that one.

On Tue, Sep 15, 2015 at 1:26 PM, Igor Tandetnik  wrote:

> On 9/15/2015 2:04 PM, John McKown wrote:
>
>> sqlite> select count(a) from x;
>>
>
> Better still:
>
> select exists (select 1 from x);
>
> The difference is that the version with count() always scans the whole
> table, while the latter stops at the first record - which is good enough if
> you only need to check for existence, and don't actually need the count.
> --
> Igor Tandetnik
>
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>



-- 

Schrodinger's backup: The condition of any backup is unknown until a
restore is attempted.

Yoda of Borg, we are. Futile, resistance is, yes. Assimilated, you will be.

He's about as useful as a wax frying pan.

10 to the 12th power microphones = 1 Megaphone

Maranatha! <><
John McKown


[sqlite] I don't understand how to use NOT EXISTS

2015-09-15 Thread John McKown
On Tue, Sep 15, 2015 at 12:43 PM, Simon Slavin  wrote:

>
> On 15 Sep 2015, at 5:01pm, Nicolas J?ger  wrote:
>
> > I also would like to know how can I check if an entry exists,(or not
> > exists), in a table. Like,
> >
> > IF (exists) THEN (doSomething) END
>
> Here's another alternative to add to those in Ryan's excellent post.  With
> your schema
>
> > create table Tags
> > (
> >  id integer primary key,
> >  name text collate nocase unique,
> >  count integer not null
> > );
>
> You can do things like
>
> SELECT total(count) FROM Tags WHERE id=234;
> SELECT total(count) FROM Tags WHERE name='biology';
>
> You will definitely get a reply from this since 'total()' returns 0.0 even
> if there are no rows which satisfy the WHERE clause.
>

Might not work. I'd use count()

sqlite> create table x(a int);
sqlite> select total(a) from x;
0.0
sqlite> select count(a) from x;
0
sqlite> insert into x values(1);
sqlite> insert into x values(-1);
sqlite> select count(a) from x;
2
sqlite> select total(a) from x;
0.0
sqlite>





>
> So you can submit this query and know that there is definitely an answer
> which is definitely a floating point value.  And then in your programming
> language you can do your equivalent of
>
> IF (theanswer) > 0.0 THEN (doSomething) END
>
> Warning: although SQLite also has the function sum() it does not produce
> the same result to total() when no lines satisfy the WHERE clause.  Sorting
> out the possibilities is more complicated.
>
> Simon.
>

-- 

Schrodinger's backup: The condition of any backup is unknown until a
restore is attempted.

Yoda of Borg, we are. Futile, resistance is, yes. Assimilated, you will be.

He's about as useful as a wax frying pan.

10 to the 12th power microphones = 1 Megaphone

Maranatha! <><
John McKown


[sqlite] I don't understand how to use NOT EXISTS

2015-09-15 Thread Nicolas Jäger
hi Keith, hi others,

> If there should only be one entry for each name (and it is not case
> sensitive), 

I'm using sqlite trough a C++ program wich take care of the case
sensitive. In this very case, each entry has to be unique.

> your best bet would be to declare that NAME is unique:
> 
> create table Tags
> (
>   id integer primary key,
>   name text collate nocase unique,
>   count integer not null
> );
> 
> Then when you want to insert you just do so, as in:
> 
> INSERT OR IGNORE INTO TAGS (name, count) VALUES
> ('magnetohydrodynamics', 0);
> 
> To increment a count you would do:
> 
> INSERT OR IGNORE INTO TAGS (name, count) VALUES
> ('magnetohydrodynamics', 0); UPDATE TAGS SET count = count + 1 WHERE
> name = 'magnetohydrodynamics';

that's definitely something I want do! thanx!

but I also would like to know how can I check if an entry exists,(or not
exists), in a table. Like,

IF (exists) THEN (doSomething) END

even if the same entry is present several times I want to execute
`doSomething` only one time.

regards,

Nicolas J.


[sqlite] I don't understand how to use NOT EXISTS

2015-09-15 Thread Nicolas Jäger
hi,
I have a table TAGS with idkey and two colums (NAME, COUNT):

id|NAME|COUNT
53|black metal|3
55|occult rock|3
61|satanic smurfs|1
62|beer|0
63|pizza|0

I want to check if some tag exist by checking if `NAME` is recorded
in the table or not. If not, I want to add it;

INSERT INTO TAGS ( NAME, COUNT ) SELECT 'magnetohydrodynamics', 1
FROM TAGS WHERE NOT EXISTS (SELECT * FROM TAGS WHERE NAME =
'magnetohydrodynamics' );

then if I look up in the table I see:

id|NAME|COUNT
53|black metal|3
55|occult rock|3
61|satanic smurfs|1
62|beer|0
63|pizza|0
64|magnetohydrodynamics|1
65|magnetohydrodynamics|1
66|magnetohydrodynamics|1
67|magnetohydrodynamics|1
68|magnetohydrodynamics|1

could you tell me please where I did some mess ?

regards,
Nicolas J.


[sqlite] I don't understand how to use NOT EXISTS

2015-09-15 Thread Nicolas Jäger
hi,
I have a table TAGS with idkey and two colums (NAME, COUNT):

id|NAME|COUNT
53|black metal|3
55|occult rock|3
61|satanic smurfs|1
62|beer|0
63|pizza|0

I want to check if some tag exist by checking if `NAME` is recorded
in the table or not. If not, I want to add it;

INSERT INTO TAGS ( NAME, COUNT ) SELECT 'magnetohydrodynamics', 1
FROM TAGS WHERE NOT EXISTS (SELECT * FROM TAGS WHERE NAME =
'magnetohydrodynamics' );

then if I look up in the table I see:

id|NAME|COUNT
53|black metal|3
55|occult rock|3
61|satanic smurfs|1
62|beer|0
63|pizza|0
64|magnetohydrodynamics|1
65|magnetohydrodynamics|1
66|magnetohydrodynamics|1
67|magnetohydrodynamics|1
68|magnetohydrodynamics|1

could you tell me please where I did some mess ?

regards,
Nicolas J.


[sqlite] I don't understand how to use NOT EXISTS

2015-09-14 Thread Keith Medcalf

On Monday, 14 September, 2015 21:07, Nicolas J?ger  
said:


> hi,
> I have a table TAGS with idkey and two colums (NAME, COUNT):

> id|NAME|COUNT
> 53|black metal|3
> 55|occult rock|3
> 61|satanic smurfs|1
> 62|beer|0
> 63|pizza|0

> I want to check if some tag exist by checking if `NAME` is recorded
> in the table or not. If not, I want to add it;

> INSERT INTO TAGS ( NAME, COUNT ) SELECT 'magnetohydrodynamics', 1
> FROM TAGS WHERE NOT EXISTS (SELECT * FROM TAGS WHERE NAME =
> 'magnetohydrodynamics' );

The problem is that the query

SELECT 'magnetohydrodynamics', 1
  FROM TAGS 
 WHERE NOT EXISTS (SELECT * 
 FROM TAGS 
WHERE NAME = 'magnetohydrodynamics'); 
returns a row for each row in tags if there is no 'magnetohydrodynamics' in 
tags.

If there should only be one entry for each name (and it is not case sensitive), 
your best bet would be to declare that NAME is unique:

create table Tags
(
  id integer primary key,
  name text collate nocase unique,
  count integer not null
);

Then when you want to insert you just do so, as in:

INSERT OR IGNORE INTO TAGS (name, count) VALUES ('magnetohydrodynamics', 0);

To increment a count you would do:

INSERT OR IGNORE INTO TAGS (name, count) VALUES ('magnetohydrodynamics', 0);
UPDATE TAGS SET count = count + 1 WHERE name = 'magnetohydrodynamics';

> then if I look up in the table I see:
> 
> id|NAME|COUNT
> 53|black metal|3
> 55|occult rock|3
> 61|satanic smurfs|1
> 62|beer|0
> 63|pizza|0
> 64|magnetohydrodynamics|1
> 65|magnetohydrodynamics|1
> 66|magnetohydrodynamics|1
> 67|magnetohydrodynamics|1
> 68|magnetohydrodynamics|1
> 
> could you tell me please where I did some mess ?
> 
> regards,
> Nicolas J.
> ___
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users