Am 13.07.2006 um 14:10 schrieb Christian Smith:

Inline.

ditto


Jens Miltner uttered:

Hi all,

I need to create a temporary table holding ID column values from a number of tables, so that I have a unique way to access the data for display purposes: say I have 2 related tables

[snip schema]

When displaying a filtered subset of the persons with all their addresses, I'd like to create a temporary table holding the person.id and address.id columns for each row being displayed:

CREATE TEMP TABLE display AS
        SELECT
                person.id as person_id,
                address.id as address_id
        FROM
                person
        LEFT JOIN
                address ON address.person_id=person.id
        WHERE
                person.name LIKE '%foo%'
        ORDER BY
                person.name,
                address.type
        ;


What purpose would this table serve? It only has ids in it, so is not any more useful for searching than the base tables, unless you're going to be using it as a cache and processing the result multiple times.

That's exactly what it is for. Basically, it's a cache for a table view in the UI that needs to have a way of identifying/addressing rows of joined data in multiple tables. Since the table view will call the controller for any row / column data it needs, my code must have a way to quickly perform random access in a view-like query result set. And no thanks, I don't want to cache the data in memory - been there, done that, but it wasn't pretty (memory-footprint-wise) ;-)





To complicate things, I have enumeration tables that are used in the display (let's say for the address type), which can also be filtered for, e.g.

CREATE TABLE address_type_enum (
        key INTEGER,
        value TEXT
);
        INSERT INTO address_type_enum (1, 'Home');
INSERT INTO address_type_enum (2, 'Work');

so that the real query to create the temp table might look like this:

CREATE TEMP TABLE display AS
        SELECT
                person.id as person_id,
                address.id as address_id
        FROM
                person
        LEFT JOIN
                address ON address.person_id=person.id
        WHERE
                person.name LIKE '%foo%'
                AND
(SELECT value FROM address_type_enum WHERE key=address.type) LIKE 'work'
        ORDER BY
                person.name,
(SELECT value FROM address_type_enum WHERE key=address.type) COLLATE NOCASE
        ;



This is horrendously complex for what you're trying to achieve. Why not just join on the address type? To get work addresses, something like:

SELECT
  person.id AS person_id,
  address.id AS address_id
FROM
  person
  LEFT JOIN address ON address.person_id=person.id
  LEFT JOIN address_type_enum ON key=address.type
WHERE
  address_type_enum.value LIKE 'work';


As I mentioned at the very end of my original mail, the real queries are much more complex and are, in fact, generated dynamically according to the user specification which columns should be displayed... The tables I specified are really just example tables to show the problem.


Would this one perform better:

CREATE TEMP VIEW display_view AS
        SELECT
                person.id as person_id,
                address.id as address_id,
                person.name as person_name,
SELECT value FROM address_type_enum WHERE key=address.type) as address_type
        FROM
                person
        LEFT JOIN
                address ON address.person_id=person.id
        WHERE
                person_name LIKE '%foo%'
                AND
                address_type LIKE 'work'
        ORDER BY
                person_name,
                address_type COLLATE NOCASE
        ;

CREATE TEMP TABLE display AS
        SELECT
                person.id as person_id,
                address.id as address_id
        FROM
                display_view
        ;


This would be a better bet. Define views to create your views by whatever criteria you see fit. Store in a temproary table for caching purposes.

Basically, the two are going to be executed right one after the other and the temp view won't be available afterwards, so the only issue I have is whether one is going to perform better than the other. Some quick and dirty test didn't show any difference - in fact for the query I tried, both ways actually produced the same byte code instructions (explain output), but this might be just for the query I chose as my example... I guess I'm looking for some better evidence that it doesn't really matter ;-)

</jum>

Reply via email to