2017-12-16 28 views
-3

毎回おもちゃを毎回お届けしている場合、より多くのお金がかかる5匹のおもちゃのリストが降順に表示されます。価格で指定された5つの最も高価なおもちゃをリストアップする(Postgres)

例えば、Ipadは600ユーロで、1,2,3歳の子供がリクエストしています。今は300ユーロの費用がかかり、3回(1回は子供1回、2回は2回)子供によって3)。私は別のおもちゃ(ラップトップ)を持っており、360€の費用がかかり、8回(子供1で2回、子供3で6回)請求されます。その後、私は見なければならない:

  1. ラップトップを合計3で3回を要求し(600€の費用がされているため、iPadは
  2. 8回を要求し、360€の費用(合計8 * 360€= 2880€)されているため、 * 600€= 1800€)
  3. 私はこれを持っている場合は、任天堂

は、私はより多くの時間が同じおもちゃを要求していること、子供のデータを見たいと思って、例えば、任天堂の場合、私はに関する情報を参照してください希望子供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

「毎回おもちゃをお届けしてもらえれば」と言われても、この言葉を使って別の言葉を使って言いたいことはありますか?あなたのテーブルにいくつかのサンプルデータを投稿して、あなたが望むものの結果の例を投稿してください。英語で説明しようとするよりも、クエリを指定するほうが簡単な場合があります:) –

+0

私は質問を編集しました。どうぞ、あなたはそれを確認できますか?私はそれがよりよく説明されることを望む。 – vikitus

答えて

1

この関数は、データ型のsetofを返します。したがって、結果を次のように選択してください:

select * from list_top_Toys(); 

その後、結果はテーブルのように操作できます。 しかし、わかりましたが、この機能にはさらに多くの変更が必要です。

2回目のクエリでは、すべてのLOOP繰り返しで同じ結果が得られるため、最初のSELECTの結果を反映するように変更し、Lettersテーブルをクエリの先頭にするように変更しました。

まず、toy_nameでグループ化する理由 - toy_idでグループ化する必要があるのはなぜですか。 また、group_name by group_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; 

私は兄弟のクエリには触れませんでした。

+0

ありがとうございました!私はあなたの変更を見て、今私は間違っていることを理解しています。 – vikitus

関連する問題