如果我们每次都交付每个玩具,我想要一个价格更高的5个玩具的清单,按降序排列。
例如,我有一个价值600欧元的Ipad,并由1号,2号和3号孩子请求。现在,我有一个任天堂,花费300欧元,要求3次(儿童1次和1次1次)孩子3)。我有另一个玩具(笔记本电脑),花费360欧元,要求8次(儿童2次2次,儿童3次6次)。然后,我必须看到:
当我有这个时,我想看到孩子的数据更多次请求相同的玩具,例如,在任天堂的情况下我想看到关于孩子2的信息。如果是笔记本电脑,我想看看有关孩子的信息3。
我创建了这种类型:
CREATE TYPE ToysList AS (
t_Toy_name VARCHAR(255),
t_Price REAL,
t_Times_requested INTEGER,
t_Total_amount_money REAL,
t_Child_name VARCHAR(255),
t_Child_times_request SMALLINT,
t_Child_address VARCHAR(255),
t_Number_Siblings SMALLINT);
表格如下:
CREATE TABLE CHILD(
child_id SMALLINT,
child_name VARCHAR(255) NOT NULL,
birth_date DATE NOT NULL,
gender VARCHAR(255) NOT NULL,
address VARCHAR(255),
city VARCHAR(255),
CONSTRAINT PK_CHILD PRIMARY KEY(child_id),
CONSTRAINT VALID_GENDER CHECK (gender IN ('m', 'f')),
CONSTRAINT VALID_DATE CHECK (birth_date <= now())
);
CREATE TABLE letter (
letter_id SMALLINT NOT NULL,
arrival_date DATE DEFAULT now() NOT NULL,
number_toys INTEGER NOT NULL,
child_id SMALLINT,
CONSTRAINT valid_child_id CHECK ((child_id IS NOT NULL)),
CONSTRAINT PK_LETTER PRIMARY KEY(letter_id),
CONSTRAINT CHILD_FK FOREIGN KEY (child_id) REFERENCES CHILD(child_id)
);
CREATE TABLE SIBLING(
child_id1 SMALLINT,
child_id2 SMALLINT,
CONSTRAINT PK_SIBLING PRIMARY KEY(child_id1, child_id2),
CONSTRAINT CHILD1_FK FOREIGN KEY (child_id1) REFERENCES CHILD(child_id),
CONSTRAINT CHILD2_FK FOREIGN KEY (child_id2) REFERENCES CHILD(child_id)
);
CREATE TABLE TOY(
toy_id SMALLINT,
toy_name VARCHAR(255) NOT NULL,
price REAL NOT NULL,
toy_type VARCHAR(255) NOT NULL,
manufacturer VARCHAR(255),
CONSTRAINT PK_TOY PRIMARY KEY(toy_id),
CONSTRAINT POSITIVE_PRICE CHECK (price > 0),
CONSTRAINT VALID_TYPE CHECK(toy_type IN ('symbolic', 'rule', 'educational', 'cooperative', 'other'))
);
CREATE TABLE WISHED_TOY(
letter_id SMALLINT,
toy_id SMALLINT,
CONSTRAINT PK_WISHED_TOY PRIMARY KEY(letter_id, toy_id),
CONSTRAINT LETTER_FK FOREIGN KEY (letter_id) REFERENCES LETTER(letter_id),
CONSTRAINT TOY_FK FOREIGN KEY (toy_id) REFERENCES TOY(toy_id)
);
此刻我这样做了:
CREATE OR REPLACE FUNCTION list_top_Toys() RETURNS SETOF ToysList AS $$
DECLARE
l_Toy_name VARCHAR(255);
l_Price REAL;
l_Times_requested INTEGER;--total times requested for this toy
l_Total_amount_money REAL; --total times requested * price toy
l_Child_name VARCHAR(255);
l_Child_times_request SMALLINT; --times request for the child
l_Child_address VARCHAR(255);
l_Number_Siblings SMALLINT;
l_toy_id INTEGER;
l_child_id INTEGER;
l_letter_id INTEGER;
returnset ToysList;
BEGIN
FOR l_toy_id, l_Toy_name, l_Times_requested, l_Total_amount_money
IN SELECT t.toy_id, t.toy_name, COUNT(*), SUM(price) AS totalAmountMoney
FROM toy t INNER JOIN wished_toy WT ON t.toy_id = WT.toy_id
GROUP BY t.toy_id, t.toy_name
ORDER BY totalAmountMoney DESC, t.toy_name
LIMIT 5
LOOP
returnset.t_Toy_name = l_Toy_name;
returnset.t_Times_requested = l_Times_requested;
returnset.t_Total_amount_money = l_Total_amount_money;
SELECT c.child_id, c.child_name, c.address, SUM(L.number_toys) AS totalToys
INTO l_child_id, l_Child_name, l_Child_address, l_Child_times_request
FROM child c
INNER JOIN letter L ON c.child_id = L.child_id
INNER JOIN wished_toy WIS ON WIS.letter_id = L.letter_id
WHERE c.child_id = l_child_id
GROUP BY c.child_id, c.child_name
ORDER BY totalToys DESC
LIMIT 1;
returnset.t_Child_name = l_Child_name;
returnset.t_Child_address = l_Child_address;
returnset.t_Child_times_request = l_Child_times_request;
SELECT COUNT(s.child_id2) AS numberSiblings
INTO l_Number_Siblings
FROM sibling s
INNER JOIN child c1 ON c1.child_id = s.child_id1
WHERE s.child_id1 = l_child_id
LIMIT 1;
returnset.t_Number_Siblings = l_Number_Siblings;
return next returnset;
END LOOP;
END;
$$LANGUAGE plpgsql;
COMMIT;
有谁能说我做错了什么?
谢谢,
答案 0 :(得分:1)
您的函数返回setof类型的数据。所以,只需从中选择结果,如下:
select * from list_top_Toys();
之后您可以使用结果操作,因为它是表格。 但是,正如我所看到的,这个功能需要更多的改变。
第二个查询在每个LOOP迭代中给出相同的结果,因此我将其更改为反映第一个SELECT的结果,并将Letters表作为查询中的前导。
首先,为什么要按toy_name分组 - 需要只有toy_id组。 此外,group by child_name(在第一个内部查询中)是多余的。 我会在结果集中包含toy_id,它可能在以后的计算中很有用。 另外,你没有按照你在帖子中说的设定玩具价格,所以首先SELECT必须有玩具的价格。
所以,我的函数版本将是:
CREATE OR REPLACE FUNCTION list_top_Toys()
RETURNS SETOF ToysList
AS $$
DECLARE
l_Toy_name VARCHAR(255);
l_Price REAL;
l_Times_requested INTEGER;--total times requested for this toy
l_Total_amount_money REAL; --total times requested * price toy
l_Child_name VARCHAR(255);
l_Child_times_request SMALLINT; --times request for the child
l_Child_address VARCHAR(255);
l_Number_Siblings SMALLINT;
l_toy_id INTEGER;
l_child_id INTEGER;
l_letter_id INTEGER;
returnset ToysList;
BEGIN
FOR l_toy_id, l_Toy_name, l_Price, l_Times_requested, l_Total_amount_money
IN SELECT t.toy_id, t.toy_name, t.price, COUNT(*), SUM(price) AS totalAmountMoney
FROM toy t
INNER JOIN wished_toy WT ON t.toy_id = WT.toy_id
GROUP BY t.toy_id
ORDER BY totalAmountMoney DESC, t.toy_name
LIMIT 5
LOOP
returnset.t_Toy_name = l_Toy_name;
returnset.t_Price = l_price;
returnset.t_Times_requested = l_Times_requested;
returnset.t_Total_amount_money = l_Total_amount_money;
SELECT c.child_id, c.child_name, c.address, SUM(L.number_toys) AS totalToys
INTO l_child_id, l_Child_name, l_Child_address, l_Child_times_request
FROM letter L
INNER JOIN child c ON c.child_id = L.child_id
INNER JOIN wished_toy WIS ON WIS.letter_id = L.letter_id
WHERE wis.toy_id = l_toy_id
GROUP BY c.child_id, c.child_name
ORDER BY totalToys DESC
LIMIT 1;
returnset.t_Child_name = l_Child_name;
returnset.t_Child_address = l_Child_address;
returnset.t_Child_times_request = l_Child_times_request;
SELECT COUNT(s.child_id2) AS numberSiblings
INTO l_Number_Siblings
FROM sibling s
INNER JOIN child c1 ON c1.child_id = s.child_id1
WHERE s.child_id1 = l_child_id
LIMIT 1;
returnset.t_Number_Siblings = l_Number_Siblings;
return next returnset;
END LOOP;
END;
$$LANGUAGE plpgsql;
我没有触摸兄弟姐妹查询。