2011-01-09 10 views
2

挨拶、1つのMySQLクエリで2つのUPDATE文を組み合わせるにはどうすればよいですか?

1は、例えば、1つのクエリで2つのUPDATE文を実行するに行くかどう

UPDATE albums SET isFeatured = '0' WHERE isFeatured = '1' 

基本的には、新しいアルバムが紹介されたときに、

UPDATE albums SET isFeatured = '1' WHERE id = '$id' 

と組み合わせます以前に特集されたアルバムは通常に戻され、新しく特集されたアルバムはアクティブに設定されます。

ありがとうございます!

答えて

7

したがって、別のテーブルfeatured_albums(FK:int id_album)を追加し、それを使ってアルバムが掲載されているかどうかを判断することをおすすめします。

あなたのアップデートが

DELETE FROM featured_album; INSERT INTO featured_album SET id_album = $id; 

基本的に私が示す行が含まれますテーブルを追加することを示唆してる以上に拡大することを要求したようテーブル

SELECT album.id, 
     album.name, 
     (id_album IS NOT NULL) AS isfeatured 
FROM album 
LEFT JOIN featured_album ON id_album = album.id 

に参加する選択となり現在選択されているアルバムこれは1対1の関係であり、すなわち、アルバムテーブル内の1つのレコードは、feature_albumsテーブル内に1つの関連するレコードを有する。 Types of Relationshipを参照してください。

Album Schema Diagram

あなたはアルバムテーブルからisFeaturedフィールドを削除し、新しいテーブルを追加します。

CREATE TABLE `featured_album` (
    `id_album` INTEGER NOT NULL, 
    FOREIGN KEY (id_album) REFERENCES `album` (`id`) 
); 

DELETE FROM ... INSERT INTO行がテーブルにエントリを作成することにより、特色アルバムを設定します。

LEFT JOINのSELECTステートメントは、アルバムテーブルのレコードをプルダウンし、featured_albumテーブルから一致するレコードを結合します。この場合、1つのレコードのみが一致します。特集アルバム以外のすべてのレコードでNULLを返します。我々は

SELECT album.id, album.name, featured_album.id_album as isFeatured0 
FROM album 
LEFT JOIN featured_album ON id_album = album.id 

をしなかった場合

だから、私たちは以下のようなものを得るだろう:すなわちisFeaturedまたはIDのNULL

+----+----------------+------------+ 
| id | name   | isFeatured | 
+----+----------------+------------+ 
| 1 | Rumours  |  NULL | 
| 2 | Snowblind  |  NULL | 
| 3 | Telegraph road |   3 | 
+----+----------------+------------+ 

。あなたがPHPで結果を処理している場合、それはすることはありませんが、最初のクエリを(id_album IS NOT NULL) AS isfeaturedを追加して使用することにより

我々は、物事をより読みやすくなりisfeaturedため

+----+----------------+------------+ 
| id | name   | isfeatured | 
+----+----------------+------------+ 
| 1 | Rumours  |   0 | 
| 2 | Snowblind  |   0 | 
| 3 | Telegraph road |   1 | 
+----+----------------+------------+ 

すなわち0/1を取得しますあなたのコードとの違い。

+0

私はこのコードに興味がありますが、決してMySQLのエキスパートではありません(明らかに)、ここで何が起こっているかをもう少し説明してもらえますか?ありがとう – NightMICU

+1

私は私の答えを拡張しました。それが意味をなされることを望む。 –

+0

ありがとうございました!私はこれを試してみる必要があります、偉大に見える – NightMICU

7

これを試してみてください:

UPDATE albums SET isFeatured = IF(id!='$id', '0','1') 
+0

+1。あなたはとても速いです。 – a1ex07

+0

old_valueが新しい場合、@Richo Mysqlは行を更新しません。 – a1ex07

+0

これはかなりわかりやすく、わかりやすいものです。ありがとう:) – NightMICU

1

あなただけのことはできません。更新する必要があるレコードのグループを1つだけ選択し、すべてのレコードに対して1つの操作しか実行できません。

UPDATE x SET col1 = 1 WHERE col1 = 0 AND col1 = 0 WHERE col1 = 1; 

これを回避する関数を使用するときは、すべての行について評価する必要があり、実際には高価になる可能性があるので注意してください。

+0

+1:実現するために、MySQLはあなたのクエリを魔法のように 'if'で書き換えてwhere句を置き換えません。 –

0

私はあなたができるとは思っていません。少なくとも、きちんとしたやり方ではありません。あなたは、PHPから1つのコールをやりたいと思っているなら

/何を、あなたは、このようにセミコロンで区切ることができます。

UPDATE albums SET isFeatured = '0' WHERE isFeatured = '1';UPDATE albums SET isFeatured = '1' WHERE id = '$id'; 
あなたは CASE WHENステートメントを使用し、必要に応じて(ELSE句の下に元の値を設定することを忘れないことができます
4

)、必要に応じてCASE条件を発注します(要求されたIDを持つ行にもisFeatured = 1がある場合、WHERE句を変更するには、以下の文でisFeaturedは0になります)。あなたはそれがあなたのデータモデルが間違っていると、いくつかの固定を行うことができます指標であるこの種のものをしなければならない

UPDATE albums 
SET isFeatured = CASE 
    WHEN isFeatured = '1' THEN '0' 
    WHEN id = '$id' THEN '1' 
    ELSE isFeatured 
END 
+0

これは本当に私を全体的に助け、将来これを使用します。ありがとう:) – NightMICU

1

MySQLは、関数内にあるときにインデックスを使用できません: MySQLでは不可能な関数のインデックスが必要です。

も参照してください。How does one create an index on the date part of DATETIME field in MySql

私は従業員のテストデータベース、それは質問を模倣するように、男性にすべての性別を設定しhttp://dev.mysql.com/doc/employee/en/employee.html

mysql> describe employees; 
+------------+---------------+------+-----+---------+-------+ 
| Field  | Type   | Null | Key | Default | Extra | 
+------------+---------------+------+-----+---------+-------+ 
| emp_no  | int(11)  | NO | PRI | NULL |  | 
| birth_date | date   | NO |  | NULL |  | 
| first_name | varchar(14) | NO |  | NULL |  | 
| last_name | varchar(16) | NO |  | NULL |  | 
| gender  | enum('M','F') | NO |  | NULL |  | 
| hire_date | date   | NO |  | NULL |  | 
+------------+---------------+------+-----+---------+-------+ 
6 rows in set (0.01 sec) 

mysql> select count(*) from employees; 
+----------+ 
| count(*) | 
+----------+ 
| 300024 | 
+----------+ 
1 row in set (0.37 sec) 

を使用しています。

mysql> update employees set gender = 'M'; 
Query OK, 1 row affected (9.11 sec) 
Rows matched: 300024 Changed: 1 Warnings: 0 

mysql> select emp_no, gender from employees order by emp_no limit 2; 
+--------+--------+ 
| emp_no | gender | 
+--------+--------+ 
| 10001 | M  | 
| 10002 | M  | 
+--------+--------+ 
2 rows in set (0.00 sec) 

従業員1人を女性に設定します。 (それがインデックスを使用して、ほぼ瞬時あることに注意してください。)

mysql> update employees set gender = 'F' where emp_no = 10001; 
Query OK, 1 row affected (0.14 sec) 
Rows matched: 1 Changed: 1 Warnings: 0 

今、私たちが提案答えを使用しています。 (インデックスを使用せず、すべての行に触れることに注意してください)

mysql> update employees set gender = if(emp_no=10002, 'F', 'M'); 
Query OK, 2 rows affected (10.67 sec) 
Rows matched: 300024 Changed: 2 Warnings: 0 

インデックスは役に立ちますか?

> mysql> create index employees_gender_idx on employees(gender); 
Query OK, 300024 rows affected (21.61 sec) 
Records: 300024 Duplicates: 0 Warnings: 0 

> mysql> update employees set gender = if(emp_no=10001, 'F', 'M'); 
Query OK, 2 rows affected (9.02 sec) 
Rows matched: 300024 Changed: 2 Warnings: 0 

Nope. 

また、変更する必要がある行だけを見ているとも言われています。

mysql> update employees set gender = 'M'; 
Query OK, 1 row affected (8.78 sec) 
Rows matched: 300024 Changed: 1 Warnings: 0 

推測しません。 WHERE句を使用するとどうなりますか?

mysql> update employees set gender = 'M' where gender ='F'; 
Query OK, 0 rows affected (0.03 sec) 
Rows matched: 0 Changed: 0 Warnings: 0 

これは速く、今ではインデックスを使用しました。

Mysqlは、IF関数が何を返すか分かりません。は、をフルテーブルスキャンする必要があります。 WHEREは本当に意味するもので、SETは本当に意味するものです。あなたは良いパフォーマンスを得るためにあなたのすべての節を整理するだけでDBを期待することはできません。

正しい解決策は、(使用インデックスは、ほぼ瞬時になります。)2つの更新

通告を発行することです、それはMySQLは魔法だけで、それを変更する必要がある行を更新知っていることを他の場所で言われました。

+0

非常に徹底的な説明、ありがとう。だから、基本的に、この種のものを組み合わせようとすると、実際には2つの別個のステートメントを送信するよりも実際には難しいですか? – NightMICU

+0

はい。 PostgreSQLなどの一部のデータベースでは、関数をインデックスできますが、MySQlはインデックスできません。あなたのテーブルが正規化されていないと言っても間違いないです(Richard Harrisonsの答えを見てください)。私は間違った情報をクリアしたかっただけです。 –

+0

明確にするために、MySQLがSET句を実際に見つけることを期待していることについて、実際にはwhere句を少し追加しました。 –

関連する問題