Re: SQL question

  • From: Gints Plivna <gints.plivna@xxxxxxxxx>
  • To: sfaroult@xxxxxxxxxxxx
  • Date: Mon, 16 Jan 2006 00:11:36 +0200

So I'm a bit upgraded this select in two ways -
(1) one have to look anly for those rows that has the given number of parts
(2) I think, that to make the result in reasonable time you should'nt
look into all combinations, let's take one specific, for example
ordered by part name

You can get (1) firstly grouping foo rows and counting them (all even
better in real life having already precalculated column not to make
full scan of this table each time)
(2) condition can be achieved using a little bit of analytics

So here it is:

select * FROM (
  select ltrim(sys_connect_by_path(part, ','), ',') combination, item
  from (
    -- this subselect is to get ONE combination (or group of combinations)
    -- for each item i.e. ,A;,A,B;,A,B,C for item 3
    select item,
           part,
           lead(part) over (partition by item order by part) np,
           row_number() over(partition by item order by part) rn
    from foo
    where item in (
      -- this is to filter out initially unnecessary items, can be replaced
      -- to something like where item_count = count_of_parts
      select item from foo
      group by item
      having count(*) = length('&ch') - length(replace('&ch', ',', '')) + 1
    )
  )
  start with rn = 1
  connect by item = prior item
      and rn = prior (rn + 1)
)
where combination='&ch'
/

for generated data as follows:
begin
  for j in 4..50 loop
    for i in 1..j loop
      insert into foo values (j, chr(i+64));
    end loop;
  end loop;
end;
/
and with following index
create index item_idx on foo (item);
it worked nicely.

As a result one always have to search for alphabetically ordered parts
i.e. A,B,C and not for example B,A,C.

Gints



On 1/13/06, Stephane Faroult <sfaroult@xxxxxxxxxxxx> wrote:
> I am not too proud of it, but it works:
>
> SQL> set verify off
> SQL> select * from foo;
>
>      ITEM PA
> ---------- --
>         1 A
>         2 A
>         2 B
>         3 A
>         3 B
>         3 C
>
> 6 rows selected.
>
> SQL> @fooquery
> Enter value for combination: A
>
>      ITEM
> ----------
>         1
>
> SQL> @fooquery
> Enter value for combination: A,B
>
>      ITEM
> ----------
>         2
>
> SQL> @fooquery
> Enter value for combination: A,B,C
>
>      ITEM
> ----------
>         3
>
> SQL> !cat fooquery.sql
> select a.item
> from (select item,
>             ltrim(sys_connect_by_path(part, ','), ',') combination,
>             level parts
>      from foo
>      connect by  nocycle item = prior item
>            and part != prior part) a,
>     (select item, count(*) cnt
>      from foo
>      group by item) b
> where a.parts = b.cnt
>  and a.item = b.item
>  and a.combination = '&combination'
> /
>
> Note that it generates all combination. Entertaining, but I wouldn't try
> it on large numbers of rows.
>
> HTH
>
> S Faroult
>
>
> On Fri, 2006-01-13 at 14:30 -0500, Sandeep Dubey wrote:
> > Hi,
> >
> > I am having tough time writing a select query. I won't blame it on
> > Friday afternoon, it is really difficult to me.
> >
> > Here is an example:
> >
> > create table foo ( item number, part varchar2(2));
> >
> > insert into foo values(1,'A');
> > insert into foo values(2,'A');
> > insert into foo values(2,'B');
> > insert into foo values(3,'A');
> > insert into foo values(3,'B');
> > insert into foo values(3,'C');
> >
> > I want to query for item that matches exact parts given in the query.
> > i.e.if I query for part A, I should get 1 ( no 2 and 3)
> >
> > If I pass A and B , I should get only 2 (no 3)
> > If I query for A, B and C, I should get only 3.
> >
> > Query can have n number of parts, It should return only that item that
> > has exact match to parts, no less no more.
> >
> > Thanks
> >
> >
> > Sandeep
> > --
> > //www.freelists.org/webpage/oracle-l
> >
>
>
> --
> //www.freelists.org/webpage/oracle-l
>
>
>
--
//www.freelists.org/webpage/oracle-l


Other related posts: