2

こんにちは StackOverflow コミュニティ:

状況

各レコードの比較方法に従って、テーブル内のすべてのレコードのランクを設定する更新クエリを作成しています。表の例:

id | budget | cost | rank | rank_score  
 1 |   500  |  20  |   ?  |     ?  
 2 |   400  |  40  |   ?  |     ?  
 3 |   300  |  40  |   ?  |     ?

したがって、この表でcostは、ランクを決定する際に最も重みがあり、次に が続きbudgetます。したがって、レコード #2 が上位にランク付けされ、レコード #3 が 2 番目、レコード #1 が最後になります。ご覧のとおり、2 つのレコードの が同じcostである場合budget、引き分けになります。

今、そのような「重み」を簡単に追跡するために、とrank_scoreの連結を保持する列を作成しています。したがって、上の表の は次のようになります。costbudgetrank_score

id | budget | cost | rank | rank_score  
 1 |   500  |  20  |   ?  |   20500   
 2 |   400  |  40  |   ?  |   40400  
 3 |   300  |  40  |   ?  |   40300  

これrank_scoreは次のように入力できます。

UPDATE table_name
SET rank_score = CONCAT(cost, budget);

問題

これまでのところすべて順調です。しかし、ここで問題が発生します。rank並べ替えなどのいくつかのために整数のみの列が必要ですが、何よりもユーザーに自分の記録のランクを表示するために必要です。もちろん、このrank列は、rank_scores の降順と等しくなります。rankしかし、サブクエリやphpでのループなどを行わずに、単一の更新クエリでこの列を計算する方法を見つけることができません.

私が試したこと

したがって、最初は次のrank_scoreような計算を取得しようとしていました。

SELECT id,
       CONCAT(cost, budget) AS rank_score
FROM table_name ;

次に、これらすべてのrank_scoresをphpでループして、次のようなクエリを作成します。

UPDATE table_name
SET rank_score = CASE id WHEN 1 THEN 20500 END,
    rank = CASE id WHEN 1 THEN 3 END
WHERE id IN (1) ;

... もちろん、このサンプルの更新クエリは完全ではありませんWHEN THEN END。テーブル内の各レコードに対してより多くの句があるためです。言うまでもなく、何千ものレコードがあると予想される場合は特に、これは見苦しいものです。

したがって、結論として、私はすでに を計算する方法を持っていますが、同じクエリで、または少なくともそのクレイジーな php ループと句を実行せずに (= ランク スコアの降順で)rank_score計算したいと考えています。rankCASE WHEN THEN END

これを読んで考えてくれてありがとう;)

明確化

@ SJuan76 の発言の明確化: ユーザーに一度に一定量のレコードが表示される場合があるため (たとえば、ユーザー ページ: SELECT * WHERE user_id = 333、1、3、または 8 レコードを取得できる)、 php 経由でランクを割り当てることはできません。彼は、各レコードのランクを知る必要があります。その場合、php を介してランクを割り当てることは機能しません。そのようなランクは、テーブル内のすべてではなく、フェッチされたレコードに関連するためです。

4

3 に答える 3

2

まず、 and を整数またはその他の数値データ型に変更budgetし、cost代わりrank_score

UPDATE table_name
SET rank_score = CONCAT(cost, budget) ;

次に、次を使用します。

UPDATE table_name
SET rank_score = cost * 1000 + budget * 1  ;

文字列関数を処理する必要がなく、次のようなものを用意する必要がないため、簡単です。

SELECT * 
FROM table_name
WHERE (conditions...)
ORDER BY rank_score DESC

(括弧: 一方のパラメーター ( 1000) を他方 ( ) よりも高く設定1することは、 の次数を持つことと同じですcost, budget。これを確認してみてください:

SELECT * 
FROM table_name
ORDER BY cost DESC
       , budget DESC

したがって、rank_scoreさまざまなパラメーター値を使用して実験を行う予定がない限り、すべてをドロップすることができます。

他の人が指摘しているように、データではなく計算を格納するフィールドを持つことはベストプラクティスではありません。非正規化です。代わりに、テーブルを正規化したままにして、データベースが必要なたびに計算を実行できるようにします。

SELECT id, budget, cost, 
       cost*1000 + budget*1 AS rank_score_calculated
FROM table_name
ORDER BY rank_score_calculated DESC

rank_score_calculated上記の例では保存されません。これにより、予算やコストが変更されたり、テーブルに新しい行が追加されたりするたびに、計算フィールドを更新する必要がなくなります。

唯一の欠点があります。テーブルが非常に大きく、そのクエリ (および計算) を多数のユーザーが非常に頻繁に実行する必要があり、テーブルが頻繁に更新される場合、データベースが遅くなる可能性があります。その場合、そのようなフィールドを追加することを考え始める必要があります。

rankもう 1 つのケースは、必要に応じて、すべてのテーブル行にわたって絶対値が必要な場合です。MySQL には「ウィンドウ」関数がないため、純粋な SQL でこのようなクエリを作成するのは非常に困難です)。


ランクは MySQL 変数を使用して計算できます

SELECT *
     , @rownum:=@rownum+1 AS rank_calculated
FROM table_name
   , (SELECT @rownum:=0) AS st
ORDER BY rank_score DESC

これらの値を に入れたい場合は、次rankを使用します。

UPDATE table_name
         JOIN
         ( SELECT id
                , @rownum:=@rownum+1 AS rank_calculated
           FROM table_name
              , (SELECT @rownum:=0) AS st
           ORDER BY rank_score DESC
         ) AS r
         ON r.id = table_name.id
SET table_name.rank = r.rank_calculated ;

上記の 2 つのクエリは純粋な SQL ではありません。Postgres、SQL-Server、Oracle など、ウィンドウ機能をサポートする別のデータベース システムに移行するオプションを検討することもできます。

于 2011-07-01T22:13:06.633 に答える
1

それを2つのクエリに分割してみましたか?またはsubqeryを使用していますか?

mysql> select p.*, (select count(0)+1 from table_name as s where s.cost >= p.cost and s.budget < p.budget) as rank from table_name as p where p.id in (1,2,3);
+----+------+--------+------+
| id | cost | budget | rank |
+----+------+--------+------+
|  1 |   20 |    500 |    3 |
|  2 |   40 |    400 |    2 |
|  3 |   40 |    300 |    1 |
+----+------+--------+------+
3 rows in set (0.00 sec)
于 2011-07-01T21:45:37.633 に答える
0

SQLは、追加のテーブルスペースを必要とせずに、また(はるかに重要なことですが)通常の形式を壊すことなく、必要に応じてレコードを既に並べ替えることができます。

また、ランクは順序から直接取得できます。必要な順序を尋ねるだけで、データを取得するときに、プログラムコードにその順序からインデックスを追加します。

なぜデータベースでこれを実行したいのですか?

于 2011-07-01T21:22:00.840 に答える