[SQL] skip if latter value equal

2009-07-10 Thread Marcin Krawczyk
Hi list,

I was wondering if it was possible for a field in SQL query to return NULL
if latter value is exactly the same ? - for given ORDER BY clause, I guess.
For example, query returns:

xxyy  1  4  true
xxyy  5  7  true
xxyy  21  8  true
yyzz  5  1 false
yyzz  7  7 false
yyzz  8  34 false

I'd like the output to be:

xxyy  1  4  true
NULL  5  7  NULL
NULL  21  8  NULL
yyzz  5  1 false
NULL  7  7 NULL
NULL  8  34 NULL

Is there any magical trick to achieve this ?

regards
mk


Re: [SQL] skip if latter value equal

2009-07-10 Thread Pavel Stehule
Hello

you can do it simply in new PostgreSQL 8.4. In older version the best
way what I know is using a stored procedure, that returns table

create or replace function foo()
returns setof yourtablename as $$
declare
  r yourtablename;
  s yourtablename;
  result youratblename;
  first boolean = true;
begin
  for r in select * from yourtablename loop order by ...
if first then
  return next r;
  s := r; first := false;
else
  if r.a is distinct from s.a then result.a := r.a else result.a
:= NULL end if;
  if r.b is distinct from s.b then result.b := r.b else result.b
:= NULL end if;
  if r.c is distinct from s.c then result.c := r.c else result.c
:= NULL end if;
  if r.d is distinct from s.d then result.d := r.d else result.d
:= NULL end if;
  return next result;
end if;
s := r;
  end loop;
  return;
end;
$$ language plpgsql;

select * from foo();

regards
Pavel Stehule

2009/7/10 Marcin Krawczyk :
> Hi list,
>
> I was wondering if it was possible for a field in SQL query to return NULL
> if latter value is exactly the same ? - for given ORDER BY clause, I guess.
> For example, query returns:
>
> xxyy  1  4  true
> xxyy  5  7  true
> xxyy  21  8  true
> yyzz  5  1 false
> yyzz  7  7 false
> yyzz  8  34 false
>
> I'd like the output to be:
>
> xxyy  1  4  true
> NULL  5  7  NULL
> NULL  21  8  NULL
> yyzz  5  1 false
> NULL  7  7 NULL
> NULL  8  34 NULL
>
> Is there any magical trick to achieve this ?
>
> regards
> mk
>

-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] skip if latter value equal

2009-07-10 Thread Marcin Krawczyk
Thanks a lot.

pozdrowienia
mk


2009/7/10 Pavel Stehule 

> Hello
>
> you can do it simply in new PostgreSQL 8.4. In older version the best
> way what I know is using a stored procedure, that returns table
>
> create or replace function foo()
> returns setof yourtablename as $$
> declare
>  r yourtablename;
>  s yourtablename;
>  result youratblename;
>  first boolean = true;
> begin
>  for r in select * from yourtablename loop order by ...
>if first then
>  return next r;
>  s := r; first := false;
>else
>  if r.a is distinct from s.a then result.a := r.a else result.a
> := NULL end if;
>  if r.b is distinct from s.b then result.b := r.b else result.b
> := NULL end if;
>  if r.c is distinct from s.c then result.c := r.c else result.c
> := NULL end if;
>  if r.d is distinct from s.d then result.d := r.d else result.d
> := NULL end if;
>  return next result;
>end if;
>s := r;
>  end loop;
>  return;
> end;
> $$ language plpgsql;
>
> select * from foo();
>
> regards
> Pavel Stehule
>
> 2009/7/10 Marcin Krawczyk :
> > Hi list,
> >
> > I was wondering if it was possible for a field in SQL query to return
> NULL
> > if latter value is exactly the same ? - for given ORDER BY clause, I
> guess.
> > For example, query returns:
> >
> > xxyy  1  4  true
> > xxyy  5  7  true
> > xxyy  21  8  true
> > yyzz  5  1 false
> > yyzz  7  7 false
> > yyzz  8  34 false
> >
> > I'd like the output to be:
> >
> > xxyy  1  4  true
> > NULL  5  7  NULL
> > NULL  21  8  NULL
> > yyzz  5  1 false
> > NULL  7  7 NULL
> > NULL  8  34 NULL
> >
> > Is there any magical trick to achieve this ?
> >
> > regards
> > mk
> >
>


[SQL] How update a table within a join efficiently ?

2009-07-10 Thread Andreas

Hi,
how would I update a table within a join in a more efficient way?

E.g. the folowing case:
table_a holds abstract elements. One column represents "priority" which 
can be based on information of other tables.
table_b might hold such details in a column "size" for about 3000 of 
8 records out of table_a.


I'd like to do this:
UPDATE table_a
SET table_a.prio = CASE WHEN size >= 10 THEN 1 ELSE 2 END
FROM table_a JOIN table_b USING (table_a_id)

This doesn't work.
But the folowing does, though it looks not efficient with those 3000 
SELECTs instead of one preparing JOIN that fetches the relevant info.  :(


UPDATE table_a
SET prio =
(
SELECT CASE WHEN size >= 10 THEN 1 ELSE 2 END
FROM table_b
WHERE table_a.table_a_id = table_b.table_a_id
)
WHERE table_a_id IN (SELECT table_a_id FROM table_b);

Is there a better way?

--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] How update a table within a join efficiently ?

2009-07-10 Thread Pavel Stehule
2009/7/10 Andreas :
> Hi,
> how would I update a table within a join in a more efficient way?
>
> E.g. the folowing case:
> table_a holds abstract elements. One column represents "priority" which can
> be based on information of other tables.
> table_b might hold such details in a column "size" for about 3000 of 8
> records out of table_a.
>
> I'd like to do this:
> UPDATE table_a
> SET table_a.prio = CASE WHEN size >= 10 THEN 1 ELSE 2 END
> FROM table_a JOIN table_b USING (table_a_id)

hello

don't repeat target table in FROM clause

UPDATE table_a
 SET table_a.prio = CASE WHEN size >= 10 THEN 1 ELSE 2 END
 FROM table_b WHERE table_a.table_a_id = table_b.table_a_id;

regards
Pavel Stehule



>
> This doesn't work.
> But the folowing does, though it looks not efficient with those 3000 SELECTs
> instead of one preparing JOIN that fetches the relevant info.  :(
>
> UPDATE table_a
> SET prio =
> (
> SELECT CASE WHEN size >= 10 THEN 1 ELSE 2 END
> FROM table_b
> WHERE table_a.table_a_id = table_b.table_a_id
> )
> WHERE table_a_id IN (SELECT table_a_id FROM table_b);
>
> Is there a better way?
>
> --
> Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-sql
>

-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


[SQL] WITH RECURSION output ordering with trees

2009-07-10 Thread Philippe Lang
Hi,

I'm playing with the new "WITH RECURSIVE" feature of 8.4. I'm trying to
figure out how to use it with trees.

Here is the test code I use:

-
--DROP TABLE recursion;

CREATE TABLE recursion
(
  id serial,
  lookup varchar(16),
  parent_id integer,
  primary key(id),
  foreign key(parent_id) references recursion(id)
);

INSERT INTO recursion VALUES(1,'a1', NULL);
INSERT INTO recursion VALUES(2,'b11',1);
INSERT INTO recursion VALUES(645,  'c111',   2);
INSERT INTO recursion VALUES(823,  'c112',   2);
INSERT INTO recursion VALUES(243,  'c113',   2);
INSERT INTO recursion VALUES(6,'b12',1);
INSERT INTO recursion VALUES(845,  'c121',   6);
INSERT INTO recursion VALUES(583,  'c122',   6);
INSERT INTO recursion VALUES(9,'b13',1);
INSERT INTO recursion VALUES(10,   'c131',   9);

WITH RECURSIVE parse_tree (depth, id, lookup, parent_id) AS
(
  SELECT 
0,
parent.id, 
parent.lookup, 
parent.parent_id 
  FROM recursion AS parent 
  WHERE parent_id IS NULL
  
  UNION ALL
  
  SELECT 
parent.depth + 1,
child.id, 
child.lookup, 
child.parent_id 
  FROM parse_tree parent, recursion AS child
  WHERE child.parent_id = parent.id
)

SELECT * FROM parse_tree;
-

Here is the result:

 depth | id  | lookup | parent_id
---+-++---
 0 |   1 | a1 |
 1 |   2 | b11| 1
 1 |   6 | b12| 1
 1 |   9 | b13| 1
 2 | 645 | c111   | 2
 2 | 823 | c112   | 2
 2 | 243 | c113   | 2
 2 | 845 | c121   | 6
 2 | 583 | c122   | 6
 2 |  10 | c131   | 9

I'd like to perform a real recursion, and show the tree structure in a
more appopriate way, like this:

 depth | id  | lookup | parent_id
---+-++---
 0 |   1 | a1 |
 1 |   2 | b11| 1
 2 | 645 | c111   | 2
 2 | 823 | c112   | 2
 2 | 243 | c113   | 2
 1 |   6 | b12| 1
 2 | 845 | c121   | 6
 2 | 583 | c122   | 6
 1 |   9 | b13| 1
 2 |  10 | c131   | 9

Any idea how to do that? (without trying to sort on the lookup column,
whose values can be random outside this test)

Best regards,

Philippe Lang

-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] WITH RECURSION output ordering with trees

2009-07-10 Thread Philippe Lang
pgsql-sql-ow...@postgresql.org wrote:
> Hi,
> 
> I'm playing with the new "WITH RECURSIVE" feature of 8.4. I'm trying
> to figure out how to use it with trees. 
> 
> Here is the test code I use:
> 
> -
> --DROP TABLE recursion;
> 
> CREATE TABLE recursion
> (
>   id serial,
>   lookup varchar(16),
>   parent_id integer,
>   primary key(id),
>   foreign key(parent_id) references recursion(id) );
> 
> INSERT INTO recursion VALUES(1,'a1', NULL);
> INSERT INTO recursion VALUES(2,'b11',1);
> INSERT INTO recursion VALUES(645,  'c111',   2);
> INSERT INTO recursion VALUES(823,  'c112',   2);
> INSERT INTO recursion VALUES(243,  'c113',   2);
> INSERT INTO recursion VALUES(6,'b12',1);
> INSERT INTO recursion VALUES(845,  'c121',   6);
> INSERT INTO recursion VALUES(583,  'c122',   6);
> INSERT INTO recursion VALUES(9,'b13',1);
> INSERT INTO recursion VALUES(10,   'c131',   9);
> 
> WITH RECURSIVE parse_tree (depth, id, lookup, parent_id) AS (
>   SELECT
> 0,
> parent.id,
> parent.lookup,
> parent.parent_id
>   FROM recursion AS parent
>   WHERE parent_id IS NULL
> 
>   UNION ALL
> 
>   SELECT
> parent.depth + 1,
> child.id,
> child.lookup,
> child.parent_id
>   FROM parse_tree parent, recursion AS child
>   WHERE child.parent_id = parent.id
> )
> 
> SELECT * FROM parse_tree;
> -
> 
> Here is the result:
> 
>  depth | id  | lookup | parent_id
> ---+-++---
>  0 |   1 | a1 |
>  1 |   2 | b11| 1
>  1 |   6 | b12| 1
>  1 |   9 | b13| 1
>  2 | 645 | c111   | 2
>  2 | 823 | c112   | 2
>  2 | 243 | c113   | 2
>  2 | 845 | c121   | 6
>  2 | 583 | c122   | 6
>  2 |  10 | c131   | 9
> 
> I'd like to perform a real recursion, and show the tree structure in
> a more appopriate way, like this: 
> 
>  depth | id  | lookup | parent_id
> ---+-++---
>  0 |   1 | a1 |
>  1 |   2 | b11| 1
>  2 | 645 | c111   | 2
>  2 | 823 | c112   | 2
>  2 | 243 | c113   | 2
>  1 |   6 | b12| 1
>  2 | 845 | c121   | 6
>  2 | 583 | c122   | 6
>  1 |   9 | b13| 1
>  2 |  10 | c131   | 9
> 
> Any idea how to do that? (without trying to sort on the lookup
> column, whose values can be random outside this test) 

Hi again,

I reply to my own post: I found a way to parse the tree with the help of
the tablefunc contrib package:

-
SELECT

t.depth,
t.id,
r.lookup,
t.parent_id

FROM connectby('recursion', 'id', 'parent_id', 'lookup', '1', 0)
AS t(id integer, parent_id integer, depth integer, o integer)

INNER JOIN recursion AS r
ON t.id = r.id
-

 depth | id  | lookup | parent_id
---+-++---
 0 |   1 | a1 |
 1 |   2 | b11| 1
 2 | 645 | c111   | 2
 2 | 823 | c112   | 2
 2 | 243 | c113   | 2
 1 |   6 | b12| 1
 2 | 845 | c121   | 6
 2 | 583 | c122   | 6
 1 |   9 | b13| 1
 2 |  10 | c131   | 9

I guess this is hard to achieve with a "WITH RECURSIVE" call.

So my question is now: is the inclusion of "START WITH... CONNECT BY"
planned for Postgresql? I read a patch had been developed for Postgresql
8.3:

http://www.postgresql-support.de/blog/blog_hans.html

Best regards,

Philippe Lang



-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] WITH RECURSION output ordering with trees

2009-07-10 Thread Thomas Kellerer

Philippe Lang, 10.07.2009 11:10:

Hi,

I'm playing with the new "WITH RECURSIVE" feature of 8.4. I'm trying to
figure out how to use it with trees.

Here is the test code I use:

I'd like to perform a real recursion, and show the tree structure in a
more appopriate way, like this:

Any idea how to do that? (without trying to sort on the lookup column,
whose values can be random outside this test)



The manual has a nice hint on this adding up IDs to "generate" a path like column that can be used for sorting. 


Try the following:

WITH RECURSIVE parse_tree (depth, id, lookup, parent_id, sort_path) AS
(
 SELECT 0, 
   parent.id, 
   cast(parent.lookup as text),
   parent.parent_id, 
   array[0] as sort_path 
 FROM recursion_sample parent 
 WHERE parent_id IS NULL

 UNION ALL
 SELECT 
   parent.depth + 1,
   child.id, 
   rpad(' ', depth * 2) || child.lookup, 
   child.parent_id,

   parent.sort_path || child.id
 FROM parse_tree parent JOIN recursion_sample child on child.parent_id = 
parent.id
)
select id, lookup
from parse_tree
order by sort_path
;

This will output:

id  | lookup
-+
  1 | a1
  2 | b11
243 |   c113
645 |   c111
823 |   c112
  6 | b12
583 |   c122
845 |   c121
  9 | b13
 10 |   c131
(10 rows)

Thomas


--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] WITH RECURSION output ordering with trees

2009-07-10 Thread Philippe Lang
pgsql-sql-ow...@postgresql.org wrote:
> Philippe Lang, 10.07.2009 11:10:
>> Hi,
>> 
>> I'm playing with the new "WITH RECURSIVE" feature of 8.4. I'm trying
>> to figure out how to use it with trees.
>> 
>> Here is the test code I use:
>> 
>> I'd like to perform a real recursion, and show the tree structure in
>> a more appopriate way, like this:
>> 
>> Any idea how to do that? (without trying to sort on the lookup
>> column, whose values can be random outside this test)
> 
> 
> The manual has a nice hint on this adding up IDs to "generate" a path
> like column that can be used for sorting. 
> 
> Try the following:
> 
> WITH RECURSIVE parse_tree (depth, id, lookup, parent_id, sort_path)
>   AS ( SELECT 0,
> parent.id,
> cast(parent.lookup as text),
> parent.parent_id,
> array[0] as sort_path
>   FROM recursion_sample parent
>   WHERE parent_id IS NULL
>   UNION ALL
>   SELECT
> parent.depth + 1,
> child.id,
> rpad(' ', depth * 2) || child.lookup,
> child.parent_id,
> parent.sort_path || child.id
>   FROM parse_tree parent JOIN recursion_sample child on
> child.parent_id = parent.id )
> select id, lookup
> from parse_tree
> order by sort_path
> ;
> 
> This will output:
> 
>  id  | lookup
> -+
>1 | a1
>2 | b11
>  243 |   c113
>  645 |   c111
>  823 |   c112
>6 | b12
>  583 |   c122
>  845 |   c121
>9 | b13
>   10 |   c131
> (10 rows)

Hi Thomas,

Thanks for your answer. Si there a built-in function that would allow
generating the sort path based on the value of the lookup column,
instead of the id, which has no meaning at all?

If yes, we would get instead:

 depth | id  | lookup | parent_id
---+-++---
 0 |   1 | a1 |
 1 |   2 | b11| 1
 2 | 645 | c111   | 2
 2 | 823 | c112   | 2
 2 | 243 | c113   | 2
 1 |   6 | b12| 1
 2 | 845 | c121   | 6
 2 | 583 | c122   | 6
 1 |   9 | b13| 1
 2 |  10 | c131   | 9

Best regards,

Philippe Lang

-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] WITH RECURSION output ordering with trees

2009-07-10 Thread Harald Fuchs
In article ,
"Philippe Lang"  writes:

> Thanks for your answer. Si there a built-in function that would allow
> generating the sort path based on the value of the lookup column,
> instead of the id, which has no meaning at all?

> If yes, we would get instead:

>  depth | id  | lookup | parent_id
> ---+-++---
>  0 |   1 | a1 |
>  1 |   2 | b11| 1
>  2 | 645 | c111   | 2
>  2 | 823 | c112   | 2
>  2 | 243 | c113   | 2
>  1 |   6 | b12| 1
>  2 | 845 | c121   | 6
>  2 | 583 | c122   | 6
>  1 |   9 | b13| 1
>  2 |  10 | c131   | 9

Try this:

WITH RECURSIVE parse_tree (depth, id, lookup, parent_id, path) AS (
  SELECT 0, parent.id, parent.lookup, parent.parent_id, parent.lookup::text
  FROM recursion AS parent
  WHERE parent_id IS NULL
UNION ALL
  SELECT parent.depth + 1, child.id, child.lookup, child.parent_id,
 parent.path || '.' || child.lookup
  FROM parse_tree parent
  JOIN recursion AS child ON child.parent_id = parent.id
)
SELECT depth, id, lookup, parent_id
FROM parse_tree
ORDER BY path


-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] WITH RECURSION output ordering with trees

2009-07-10 Thread Philippe Lang
pgsql-sql-ow...@postgresql.org wrote:
> In article
> ,
> "Philippe Lang"  writes: 
> 
>> Thanks for your answer. Si there a built-in function that would allow
>> generating the sort path based on the value of the lookup column,
>> instead of the id, which has no meaning at all?
> 
>> If yes, we would get instead:
> 
>>  depth | id  | lookup | parent_id
>> ---+-++---
>>  0 |   1 | a1 |
>>  1 |   2 | b11| 1
>>  2 | 645 | c111   | 2
>>  2 | 823 | c112   | 2
>>  2 | 243 | c113   | 2
>>  1 |   6 | b12| 1
>>  2 | 845 | c121   | 6
>>  2 | 583 | c122   | 6
>>  1 |   9 | b13| 1
>>  2 |  10 | c131   | 9
> 
> Try this:
> 
> WITH RECURSIVE parse_tree (depth, id, lookup, parent_id, path) AS (
>   SELECT 0, parent.id, parent.lookup, parent.parent_id,
>   parent.lookup::text FROM recursion AS parent
>   WHERE parent_id IS NULL
> UNION ALL
>   SELECT parent.depth + 1, child.id, child.lookup, child.parent_id,
>  parent.path || '.' || child.lookup
>   FROM parse_tree parent
>   JOIN recursion AS child ON child.parent_id = parent.id
> )
> SELECT depth, id, lookup, parent_id
> FROM parse_tree
> ORDER BY path

Works great, thanks! Of course, concatenating lookups...

Best regards,

Philippe

-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql