Re: Question on a select - Mailing list pgsql-general

From Madison Kelly
Subject Re: Question on a select
Date
Msg-id 41D799D4.4020103@alteeve.com
Whole thread Raw
In response to Re: Question on a select  ("Vincent Hikida" <vhikida@inreach.com>)
List pgsql-general
Vincent Hikida wrote:
> There are several ways. I am making the simplifying assumption that
> name, type and dir cannot be NULL in either table. If they are the query
> is a little more complicated.
>
> The following are a couple of many techniques.
>
> SELECT a.a_name
>             , a.a_type
>             , a.a_dir
>     FROM a_table a
>  WHERE NOT EXISTS
>              ( SELECT NULL
>                     FROM b_table b
>                  WHERE b.b_name      = a.a_name
>                        AND b.b_type        = a.a_type
>                        AND b.b_dir          = a.a_dir
>              )
>
> SELECT a.a_name
>             ,  a.a_type
>             ,  a.a_dir
>    FROM a_table      a
>                 LEFT JOIN b_table b
>                        ON  a.a_table    = b.b_table
>                      AND a.a_type     = b.b_type
>                      AND a.a_dir       = b.b_type
> WHERE b.b_table IS NULL                           // assumes that
> b.b_table is a not null column.
>
> Let's say that dir could be null and dir is a string, then (assuming
> that dir can never be 'xyz') you could say something like
>
> COALESCE(a.a_dir,'xyz')  = COALESCE(b.b_dir,'xyz')
>
> Since NULL never equal NULL, if you want NULL in one table to match a
> NULL in another table, you need to change it to something not NULL.
> However this depends on what you want in your application.
>
> Queries like this are used often to check the integrity of your data.
> Examples of this are 1) What orders don't have order items?  2) What
> books have no authors? etc.

   This is wonderful! Thank you for responding so quickly! :) I should
mention that I am still very much learning so I apologise in advance if
I miss the obvious. ^.^;

   They are all 'not null' and I am trying to do exactly the kind of
task you described. I tried the first example on my DB and got a syntax
error:

tle-bu=> SELECT a.file_name, a.file_parent_dir, a.file_type FROM
file_info_1 a WHERE NOT EXIST (SELECT NULL FROM file_set_1 b WHERE
b.fs_name=a.file_name, b.fs_parent_dir=a.file_parent_dir,
b.fs_type=a.file_type);
ERROR:  syntax error at or near "SELECT" at character 88

   The second example you gave seems to work perfectly (as I will show
near the bottom of this email). What are the benefits and down sides of
each method? Is there a simple reason why the first method failed
(probably a typo I imagine...)?


   A little more specifics about my DB:

   'file_info_1' and 'file_set_1' are two tables I use to store
information of files and directories (this is a backup program).

   'file_info_#' stores dynamic info like file size, owner and such.
This table is dropped and recreated before a new scan of the partition
creates a mass 'COPY' load (the '_1' indicates the first partition).

   'file_set_#' stores static information such as "has the file been
selected for backup" which is why I keep it in a separate table. I want
to run this select first to write entries for newly added files and
directories (the values will match the file's parent) and then again in
reverse to remove from 'file_set_#' entries that no longer exist on the
partition.

   If it helps, here is the structure of the tables:

CREATE TABLE file_info_ID (
    file_acc_time        bigint        not null,
    file_group_name        varchar(255)    not null,
    file_group_uid        int        not null,
    file_mod_time        bigint        not null,
    file_name        varchar(255)    not null,
    file_parent_dir        varchar(255)    not null,
    file_perm        varchar(10)    not null,
    file_size        bigint        not null,
    file_type        varchar(2)    not null    default 'f',
    file_user_name        varchar(255)    not null,
    file_user_uid        int        not null
);

CREATE TABLE file_set_# (
    fs_backup        boolean        not null    default 't',
    fs_display        boolean        not null    default 'f',
    fs_name            varchar(255)    not null,
    fs_parent_dir        varchar(255)    not null,
    fs_restore        boolean        not null    default 'f',
    fs_type            varchar(2)    not null    default 'f'
);

   And here is some sample data that I have to work with (yes, it's a
win2k partition... I use it to test other aspects of my program and, if
I blow it away, I won't be upset. ^.^; All of this is being done on a
Fedora Core 3 install in case it makes a difference):

tle-bu=> SELECT file_type, file_parent_dir, file_name FROM file_info_1
WHERE file_parent_dir='/' LIMIT 30;
  file_type | file_parent_dir |       file_name
-----------+-----------------+------------------------
  d         | /               | .
  d         | /               | downloads
  d         | /               | Documents and Settings
  d         | /               | Program Files
  f         | /               | io.sys
  f         | /               | msdos.sys
  f         | /               | _NavCClt.Log
  d         | /               | WUTemp
  d         | /               | Recycled
  f         | /               | pagefile.sys
  d         | /               | winnt
  f         | /               | ntldr
  f         | /               | ntdetect.com
  f         | /               | boot.ini
  f         | /               | config.sys
  f         | /               | autoexec.bat
  f         | /               | t5r4e3w2q1.exe
  f         | /               | 1q2w3e4r5t.exe
  f         | /               | logon.exe
  f         | /               | arcldr.exe
  f         | /               | arcsetup.exe
(21 rows)

tle-bu=> SELECT fs_type, fs_parent_dir, fs_name FROM file_set_1 WHERE
fs_parent_dir='/' LIMIT 30;
  fs_type | fs_parent_dir |        fs_name
---------+---------------+------------------------
  d       | /             | .
  d       | /             | downloads
  d       | /             | Documents and Settings
  d       | /             | Program Files
  d       | /             | WUTemp
  d       | /             | Recycled
  d       | /             | winnt
(7 rows)

   In this example I deleted manually all the 'f' entries so that when I
do the select I should get:

  file_type | file_parent_dir |       file_name
-----------+-----------------+------------------------
  f         | /               | io.sys
  f         | /               | msdos.sys
  f         | /               | _NavCClt.Log
  f         | /               | pagefile.sys
  f         | /               | ntldr
  f         | /               | ntdetect.com
  f         | /               | boot.ini
  f         | /               | config.sys
  f         | /               | autoexec.bat
  f         | /               | t5r4e3w2q1.exe
  f         | /               | 1q2w3e4r5t.exe
  f         | /               | logon.exe
  f         | /               | arcldr.exe
  f         | /               | arcsetup.exe

   Which is exactly what your second example provides:

tle-bu=> SELECT a.file_name, a.file_parent_dir, a.file_type FROM
file_info_1 a LEFT JOIN file_set_1 b ON a.file_name=b.fs_name AND
a.file_parent_dir=b.fs_parent_dir AND a.file_type=b.fs_type WHERE
b.fs_name IS NULL;
    file_name    | file_parent_dir | file_type
----------------+-----------------+-----------
  1q2w3e4r5t.exe | /               | f
  arcldr.exe     | /               | f
  arcsetup.exe   | /               | f
  autoexec.bat   | /               | f
  boot.ini       | /               | f
  config.sys     | /               | f
  io.sys         | /               | f
  logon.exe      | /               | f
  msdos.sys      | /               | f
  _NavCClt.Log   | /               | f
  ntdetect.com   | /               | f
  ntldr          | /               | f
  pagefile.sys   | /               | f
  t5r4e3w2q1.exe | /               | f
(14 rows)

   Thank you very much for your help!

Madison

pgsql-general by date:

Previous
From: Eric Scott
Date:
Subject: Re: Can't change password?
Next
From: Madison Kelly
Date:
Subject: Re: Question on a select