2011-07-05 13 views
5

私はURLのテーブルを持っていて、1つの属性がドメインです。同じ属性を持つ限られた数の行を選択する方法は?

私がeBayからグーグル、フェイスブックから100、100および他のドメインの同じから100件のURLを持っていますが、私は他の人からグーグル、フェイスブックから30、イーベイから30および30からの最初の30件のURLを取得したいと仮定すると最大500のURLに制限します。私はこれを行う方法

+0

? 16以上の場合は、どのようにクエリが動作する必要がありますか? –

+0

はい、16以上です。ドメインごとに30を選択すると最大制限を超える場合は、URLの取得を停止してください。例:制限が70の場合は、Googleから30、Facebookから30、Ebayから10、その他からは1つを取得します。 –

+1

どのドメインに優先権が必要ですか?それはどうやって決定されますか? –

答えて

2

次のSQLは、私の場合を解決しますが、ROW_NUMBERは注文に従わないので、URLは順不同です。私はこのSQLにいくらか改善が必要だと思います。あなたがそのテーブルに持っているどのように多くのドメイン

SELECT url,row_number FROM(
    SELECT url,row_number() OVER (PARTITION BY domain) FROM website 
    WHERE domain IN 
    (SELECT DISTINCT domain FROM link) 
) AS links 
WHERE row_number <= 10 
LIMIT 25 
+0

あなたは 'PARTITION BY domain ORDER BY ctid'と書くことも、注文のために他の列を指定することもできます。とにかく、良い答え。 –

1

どのようにこのようなものについて:

SELECT url FROM link WHERE domain='Google' LIMIT 30 
UNION 
SELECT url FROM link WHERE domain='Facebook' LIMIT 30 
UNION 
SELECT ... 

など

+0

私は '「グーグル」を選択し追加することをお勧め、URL .... SELECTのFacebook '、URL ...'ので、彼はどこからだった伝えることができます。 – JNK

+0

しかし、あなたはそれの最後に 'LIMIT 70'を置くことができますか? –

+1

ことが – duduamar

1

ベースのPL/pgSQLでは私のソリューション。ここで

CREATE OR REPLACE FUNCTION getURLs(singleLimit integer, totalLimit integer) 
RETURNS SETOF RECORD AS $$ 
DECLARE 
    dom text; 
    nrOfDomains integer; 
    i integer; 
    lim integer; 
    remainder integer; 
BEGIN 
    nrOfDomains := totalLimit/singleLimit; -- integer division (truncate) 
    remainder := totalLimit%singleLimit; 

    IF remainder <> 0 THEN 
     nrOfDomains := nrOfDomains + 1; 
    END IF; 

    i := 1; 
    FOR dom IN SELECT DISTINCT domain FROM website LIMIT nrOfDomains 
    LOOP 
     IF i = nrOfDomains AND remainder <> 0 THEN 
      lim := remainder; 
     ELSE 
      lim := singleLimit; 
     END IF; 

     RETURN QUERY SELECT * FROM website WHERE domain = dom LIMIT lim; 

     i := i + 1; 
    END LOOP; 
    RETURN; 
END $$ 
LANGUAGE 'plpgsql'; 

いくつかのテスト - である:私はそれはあなたが直接結果を取得するためにその機能を使用することができている、あなたは(関数の体内でそのテーブルに INSERTを使用して)追加の一時テーブルを必要としないこと、より良い方法を発見しましたドライブ:

postgres=> CREATE TABLE website(url text, domain text); 
CREATE TABLE 

postgres=> INSERT INTO website 
    SELECT 'http://' || d.column1 ||'/' || n, d.column1 
    FROM generate_series(1, 100) n CROSS JOIN 
    (VALUES ('google'), ('facebook'), ('ebay')) d; 
INSERT 0 300 

postgres=> SELECT * FROM getURLs(10, 25) website(url text, domain text); 

結果:

 url   | domain 
--------------------+---------- 
http://google/1 | google 
http://google/2 | google 
http://google/3 | google 
http://google/4 | google 
http://google/5 | google 
http://google/6 | google 
http://google/7 | google 
http://google/8 | google 
http://google/9 | google 
http://google/10 | google 
http://facebook/1 | facebook 
http://facebook/2 | facebook 
http://facebook/3 | facebook 
http://facebook/4 | facebook 
http://facebook/5 | facebook 
http://facebook/6 | facebook 
http://facebook/7 | facebook 
http://facebook/8 | facebook 
http://facebook/9 | facebook 
http://facebook/10 | facebook 
http://ebay/1  | ebay 
http://ebay/2  | ebay 
http://ebay/3  | ebay 
http://ebay/4  | ebay 
http://ebay/5  | ebay 
(25 rows) 
+1

「IF 500%30 <> 0」と書いた理由は分かりますが、それでも私は笑われました。 :) –

+1

+1。それはあなたがしたい場合は、ドメインがランダムにあなたが 'FOR Dでは')RAND(BYサイトLIMIT nrOfDomains ORDERは異なるドメインを選択を使用することができます発注することは注目に値します、またはあなたは彼らがその場で他の方法で注文する場合はそれをするために。 –

+0

@Chris Cunningham:はい、私は '500%30'をより一般的な' totalLimit%singleLimit'に変更しました。 –

関連する問題