sql >> データベース >  >> RDS >> Mysql

MySQLの複雑なサブクエリの定式化

    スキーマについてStrawberryに同意します。パフォーマンスを向上させるためのアイデアなどについて話し合うことができます。しかし、これは、いくつかのチャットと質問への変更の後にこれを解決する方法についての私の見解です。

    以下のデータは、そのテーブルに画像がない本やタイブレークなど、さまざまな境界条件に対処するために変更されていることに注意してください。 max(upvotes)を使用したタイブレークの意味 。 OPは質問を数回変更し、画像テーブルに新しい列を追加しました。

    変更されたquetionは、1冊あたり1行の返品になりました。それをスクラッチします。画像がない場合でも、常に1冊あたり1行です。返される画像情報は、最大賛成票の画像情報になります。

    本の表

    create table books 
    (   id int primary key, 
        name varchar(1000), 
        releasedate date, 
        purchasecount int
    ) ENGINE=InnoDB;
    
    insert into books values(1,"fool","1963-12-18",456);
    insert into books values(2,"foo","1933-12-18",11);
    insert into books values(3,"fooherty","1943-12-18",77);
    insert into books values(4,"eoo","1953-12-18",678);
    insert into books values(5,"fooe","1973-12-18",459);
    insert into books values(6,"qoo","1983-12-18",500);
    

    元の質問からのデータ変更。

    主に新しいupvotes 列。

    以下に、追加されたタイブレーク行が含まれています。

    create table images 
    (   bookid int, 
        poster varchar(150) primary key, 
        bucketid int, 
        upvotes int -- a new column introduced by OP
    ) ENGINE=InnoDB;
    
    insert into images values (1,"xxx",12,27);
    insert into images values (5,"pqr",11,0);
    insert into images values (5,"swt",11,100);
    insert into images values (2,"yyy",77,65);
    insert into images values (1,"qwe",111,69);
    insert into images values (1,"blah_blah_tie_break",111,69);
    insert into images values (3,"qwqqe",14,81);
    insert into images values (1,"qqawe",8,45);
    insert into images values (2,"z",81,79);
    

    派生テーブルの視覚化

    これは、最終的なクエリの内部を視覚化するのに役立つだけです。これは、タイブレーク状況の落とし穴、つまりrownumを示しています。 変数。その変数は、bookidごとに1にリセットされます。 それ以外の場合は増分します。最後に(最後のクエリ)、rownum=1のみが必要です。 1冊あたり最大1行が返されるように行します(存在する場合)。

    最終クエリ

    select b.id,b.purchasecount,xDerivedImages2.poster,xDerivedImages2.bucketid
    from books b
    left join
    (   select i.bookid,i.poster,i.bucketid,i.upvotes,
        @rn := if(@lastbookid = i.bookid, @rn + 1, 1) as rownum,
        @lastbookid := i.bookid as dummy
        from 
        (   select bookid,max(upvotes) as maxup
            from images
            group by bookid
        ) xDerivedImages
        join images i
        on i.bookid=xDerivedImages.bookid and i.upvotes=xDerivedImages.maxup
        cross join (select @rn:=0,@lastbookid:=-1) params
        order by i.bookid
    ) xDerivedImages2
    on xDerivedImages2.bookid=b.id and xDerivedImages2.rownum=1
    order by b.purchasecount desc
    limit 10
    

    結果

    +----+---------------+---------------------+----------+
    | id | purchasecount | poster              | bucketid |
    +----+---------------+---------------------+----------+
    |  4 |           678 | NULL                |     NULL |
    |  6 |           500 | NULL                |     NULL |
    |  5 |           459 | swt                 |       11 |
    |  1 |           456 | blah_blah_tie_break |      111 |
    |  3 |            77 | qwqqe               |       14 |
    |  2 |            11 | z                   |       81 |
    +----+---------------+---------------------+----------+
    

    cross joinの重要性 2つの変数の開始値を導入して設定するだけです。以上です。

    結果は、purchasecountの降順で上位10冊の本です。 imagesからの情報 存在する場合(それ以外の場合はNULL )最も賛成の画像の場合。選択された画像は、rownumを使用した視覚化セクションで前述したように、最初のルールを選択するタイブレークルールを尊重します。 。

    最終的な考え

    適切なwhereにくさびを入れるのはOPに任せます 与えられたサンプルデータには検索するのに役立つ本の名前がなかったため、最後に句があります。その部分は些細なことです。ああ、そして主キーの幅が広いスキーマについて何かをしなさい。しかし、それは現時点ではトピックから外れています。




    1. どのMySQL照合がPHPの文字列比較と完全に一致しますか?

    2. ユリウス日をPostgreSQLの日付に変換する

    3. PostgreSQL:条件が真になるまでループする

    4. psqlの戻り値/それを呼び出したシェルスクリプトを強制終了するエラー?