2

I have got a table with columns (srno, Name, Product, Amount). The values are

(1,    Ronak, Iphone,  40000),
                (2,    Ronak, Iphone,  36000),
                (3,    Ronak, Iphone,  38000),
                (4,    Naman, Iphone,  40000),
                (5,    Naman, Ipad,    20000),
                (6,    Nihar, Ipad,    20000),
                (7,    Ronak, Ipad,    19000),
                (8,    Naman, Iphone,  37000),
                (9,    Nihar, Ipad,    40000),

I want to fetch the distinct values and store it in another table with their respective parent_id. The output should be like below:

(uid, name, parent_id)
(1,  Ronak,   NULL),
(2,  Naman,   NULL),
(3,  Nihar,   NULL),
(4,  Iphone,  1),
(5,  Iphone,  2),
(6,  Ipad,    2),
(7,  Ipad,    3),
(8,  Ipad,    1),
(9,  40000,   4),
(10, 36000,   4),
(11, 38000,   4),
(12, 40000,   5),
(13, 20000,   6),
(14, 20000,   7),
(15, 19000,   8),
(16, 37000,   5),
(17, 40000,   7),

The parent_id is the uid from the same table

Can anyone tell me what query in postgresql can achieve me the desired output. I am using PHP and PostgreSQL.

4

2 回答 2

1

这可以完成工作,但每个添加的列都需要一个步骤。我不认为它可以用递归 CTE 来完成(也许用辅助阵列)。顺便说一句:奇怪的存储层次结构!

CREATE TABLE oldstuff
        ( num INTEGER NOT NULL PRIMARY KEY
        , name varchar NOT NULL
        , thing varchar NOT NULL
        , figure INTEGER NOT NULL
        , UNIQUE (name,thing,figure)
        );

INSERT INTO oldstuff(num,name,thing,figure) VALUES
(1, 'Ronak', 'Iphone',  40000),
(2, 'Ronak', 'Iphone',  36000),
(3, 'Ronak', 'Iphone',  38000),
(4, 'Naman', 'Iphone',  40000),
(5, 'Naman', 'Ipad',    20000),
(6, 'Nihar', 'Ipad',    20000),
(7, 'Ronak', 'Ipad',    19000),
(8, 'Naman', 'Iphone',  37000),
(9, 'Nihar', 'Ipad',    40000);

CREATE TABLE newstuff
        ( num SERIAL NOT NULL PRIMARY KEY
        , thing varchar NOT NULL
        , parent_num INTEGER REFERENCES newstuff(num)
        , UNIQUE (thing,parent_num)
        );

INSERT INTO newstuff(thing)
SELECT DISTINCT os.name
FROM oldstuff os
GROUP BY os.name
        ;

INSERT INTO newstuff(thing,parent_num)
SELECT DISTINCT os.thing, ns.num
FROM oldstuff os
LEFT JOIN newstuff ns ON ns.thing= os.name
GROUP BY os.thing, ns.num
        ;

INSERT INTO newstuff(thing,parent_num)
SELECT os.figure::varchar, COALESCE(n1.num,n0.num)
FROM oldstuff os
JOIN newstuff n0 ON n0.thing= os.name AND n0.parent_num IS NULL
JOIN newstuff n1 ON n1.thing= os.thing AND n1.parent_num =n0.num
        ;

SELECT * FROM newstuff ;

结果:

   num | thing  | parent_num 
-----+--------+------------
   1 | Naman  |           
   2 | Ronak  |           
   3 | Nihar  |           
   4 | Ipad   |          1
   5 | Ipad   |          2
   6 | Ipad   |          3
   7 | Iphone |          1
   8 | Iphone |          2
   9 | 20000  |          4
  10 | 37000  |          7
  11 | 40000  |          7
  12 | 19000  |          5
  13 | 36000  |          8
  14 | 38000  |          8
  15 | 40000  |          8
  16 | 20000  |          6
  17 | 40000  |          6
于 2013-09-30T11:17:32.553 回答
0

也许它可以通过更容易的连接来完成,但我认为最有效的方法是使用窗口函数:

with cte as (
    select
        t.Name, t.Product, t.Amount,
        dense_rank() over(order by t.Name) as Name_ID,
        dense_rank() over(order by t.Product, t.Name) as Product_ID,
        dense_rank() over(order by t.Product, t.Name, t.Amount) as Amount_ID
    from Table1 as t
), cte2 as (
    select
        Name, Product, Amount,
        Name_ID,
        max(Name_ID) over() + Product_ID as Product_ID,
        max(Name_ID) over() + max(Product_ID) over() + Amount_ID as Amount_ID
    from cte
)
select distinct
    Name_ID as uid, Name as name, null::int as parent_id
from cte2

union all

select distinct
    Product_ID as uid, Product as name, Name_ID as parent_id
from cte2

union all

select distinct
    Amount_ID as uid, Amount::varchar(10) as name, Product_ID as parent_id
from cte2
order by uid, parent_id

sql fiddle demo

于 2013-09-30T10:22:57.893 回答