2

RoR アプリケーションで結合したい 2 つの PostgreSQL ステートメントがあります。

最初の SQL ステートメントは、2 つの特定の tag_id を含むリンクを返します。

SELECT link_id, count(*) as counter
  FROM "totals"
 WHERE "totals"."tag_id" IN (6, 8)
   AND (score > 0)
 GROUP BY link_id
HAVING count(*)=2

RoR ActiveRecord バージョン:

 links = Total.find_all_by_tag_id(@tag_list, :conditions => ["score > 0"], :select => "link_id, count(*) as counter", :having => "count(*)=#{@tag_list.count}", :group => "link_id").collect(&:link_id).uniq.sort.reverse

2 番目の SQL ステートメントは、特定の tag_id のスコアが最も高いリンクを返します。

SELECT s1.link_id
  FROM totals AS s1
     , (SELECT link_id
              , MAX(score) AS maxscore
          FROM totals
         GROUP BY link_id) as s2
 WHERE s2.link_id = s1.link_id
   and s1.score = s2.maxscore
   AND s1.score > 0 AND s1.tag_id = 6

テーブルは次のように構成されます。

totals:
  link_id : integer
  tag_id : integer
  score : integer

=============================
| link_id  | tag_id | score |
=============================
|    1     |    6   |   5   |
|    1     |    8   |   2   |
|    1     |    3   |   1   |
|    2     |    6   |   6   |
|    2     |    4   |   2   |
|    2     |    8   |   6   |
|    3     |    6   |   5   |
|    3     |    2   |   4   |
|    4     |    2   |   4   |
|    4     |    6   |   1   |
|    4     |    8   |   2   |
=============================

最初の SQL ステートメントは を返しlink_ids 1, 2 and 4、2 番目の SQL ステートメントは を返しlink_ids 1, 2 and 3ます。

複数の選択されたタグを含む特定のタグの最高スコアを取得するために、2 つの SQL ステートメントを 1 つに結合するにはどうすればよいですか?

結合されたステートメントは、link_ids 1 and 2.

DDL および INSERT コマンドは、http ://sqlize.com/480glD5Is4 にあります。

これが RoR ActiveRecord スタイルまたはより最適な SQL ステートメントで記述できれば素晴らしいことです。

どうもありがとう。

4

1 に答える 1

1

最初の SQL ステートメントは、2 つの特定の tag_id を含むリンクを返します。

これは、{link_id, tag_id} に主キー制約または一意制約がある場合にのみ機能します。私はその制約を追加し (理にかなっています)、他の人のために CREATE TABLE および INSERT ステートメントを含めます。(あなたはそれをしているはずです。必要に応じて、質問を編集してこの内容を貼り付けてください。)

create table totals (
  link_id  integer not null,
  tag_id integer not null,
  score integer not null,
  primary key (link_id, tag_id)
);

insert into totals values
(1, 6, 5   ),
(1, 8, 2   ),
(1, 3, 1   ),
(2, 6, 6   ),
(2, 4, 2   ),
(3, 6, 1   ),
(3, 2, 4   ),
(3, 8, 3   ),
(4, 2, 4   ),
(4, 6, 1   ),
(4, 8, 2   );

コメントに基づいて質問を言い換えると、リンクID番号を探しています

  • タグ ID 番号 6 と 8 の両方、および
  • タグ ID 6 のスコアがタグ ID 8 のスコアよりも高い

まず、これら 2 つのクエリでスコアが得られることは簡単にわかります。

  • tag_id = 6 を持つすべての行、および
  • tag_id = 8 を持つすべての行

    select *
    from totals
    where tag_id = 6
    
    select *
    from totals
    where tag_id = 8
    

それはとても簡単です。

共通のテーブル式を使用して、2 つのクエリを簡単に結合できます。

with score_for_8 as (
  select *
  from totals
  where tag_id = 8
) 
select totals.* 
from totals 
inner join score_for_8
        on score_for_8.link_id = totals.link_id and
           totals.score > score_for_8.score 
where totals.tag_id = 6;

これは結果セットのグループ化、順序付け、または制限を必要としないため、同順位を正しく報告します。

これはまだあなたが探しているものではないと確信していますが、あなたの最後のコメントは理解できません.

于 2011-11-19T15:54:57.360 に答える