2

1行をmysqlの同じデータを持つ5行に置き換えるにはどうすればよいですか。たとえば、このテーブルがあります

 id   |   companyId   |      name       |  open  |  close
 1    |    1          |    mon-fri      |  10:00 |  19:00  
 2    |    1          |      sat        |  10:00 |  12:00 
 3    |    1          |      sun        |  10:00 |  12:00 
 4    |    2          |    mon-fri      |  10:00 |  16:00  
 5    |    2          |      sat        |  10:00 |  13:00 
 6    |    2          |      sun        |  10:00 |  13:00 

名前フィールドの mon-fri を mon 、 tues 、 wed 、 thur 、 fri に変換したい。

 id   |   companyId   |      name       |  open  |  close
 1    |    1          |    mon     |  10:00 |  19:00  
 2    |    1          |    tues    |  10:00 |  19:00 
 3    |    1          |    wed     |  10:00 |  19:00 
 4    |    1          |    thur    |  10:00 |  19:00   
 5    |    1          |    fri     |  10:00 |  19:00  
 6    |    1          |    sat     |  10:00 |  12:00 
 7    |    1          |    sun     |  10:00 |  12:00 
.
.
.
4

1 に答える 1

4

を介してこれを行うことはできませんUPDATEが、できることは、一連のINSERT INTO ... SELECT文字列リテラルを使用してDELETEから、展開した行を削除することです。

/* First insert a row for each mon,tue,wed,thur,fri */
/* Column values are copied from the existing mon-fri row, and use the literal strings 'mon', 'tue', etc as the new `name` */
INSERT INTO yourtable (`companyId`, `name`, `open`, `close`)
  SELECT `companyId`, 'mon', `open`, `close` FROM yourtable WHERE `name` = 'mon-fri'
INSERT INTO yourtable (`companyId`, `name`, `open`, `close`)
  SELECT `companyId`, 'tue', `open`, `close` FROM yourtable WHERE `name` = 'mon-fri'
INSERT INTO yourtable (`companyId`, `name`, `open`, `close`)
  SELECT `companyId`, 'wed', `open`, `close` FROM yourtable WHERE `name` = 'mon-fri'
INSERT INTO yourtable (`companyId`, `name`, `open`, `close`)
  SELECT `companyId`, 'thur', `open`, `close` FROM yourtable WHERE `name` = 'mon-fri'
INSERT INTO yourtable (`companyId`, `name`, `open`, `close`)
  SELECT `companyId`, 'fri', `open`, `close` FROM yourtable WHERE `name` = 'mon-fri'

/* Then delete the original mon-fri rows which you just expanded out */
DELETE FROM yourtable WHERE `name` = 'mon-fri'

http://sqlfiddle.com/#!2/cae33/1

(当然のことながら、この優れた提案は、一方的な編集によるAndriy Mの作業でした)

次のように、仮想テーブルを使用して、ステートメントの数とテーブル スキャンの数を減らすこともできます。

/* Cross-join the existing 'mon-fri' rows with a virtual table of day names
   of 'mon' through 'fri' and insert the resulting set back into your table */
INSERT INTO yourtable (`companyId`, `name`, `open`, `close`)
  SELECT t.`companyId`, v.`name`, t.`open`, t.`close`
  FROM yourtable t
  CROSS JOIN (
    SELECT 'mon' AS `name` UNION ALL
    SELECT 'tue' UNION ALL
    SELECT 'wed' UNION ALL
    SELECT 'thur' UNION ALL
    SELECT 'fri'
  ) v
  WHERE t.`name` = 'mon-fri';

/* Then delete the original mon-fri rows which you just expanded out */
DELETE FROM yourtable WHERE `name` = 'mon-fri';

http://sqlfiddle.com/#!2/98e35/1

コメント後の更新:

行を挿入するときにそれらの順序を強制することに実際の価値はありません。これは で行うのが最適SELECTです。

それぞれを日単位で注文するにcompanyIdは、どの方法をとっても手間がかかります。LOWER(STR_TO_DATE())withを呼び出して曜日の値を比較することもできますが、MySQL ではこのように省略されるため、to%aを変更する必要もあります。その結果、一連の関数呼び出しが発生します。 thurthu

代わりに、 で a を使用してCASE....、次のORDER BYように序数値を各日に割り当てることができます。

ORDER BY
 companyId,
 CASE `name`
   WHEN 'sun' THEN 1 
   WHEN 'mon' THEN 2
   WHEN 'tue' THEN 3
   WHEN 'wed' THEN 4
   WHEN 'thur' THEN 5
   WHEN 'fri' THEN 6
   WHEN 'sat' THEN 7
 ELSE 8 END

ただし、上記の方法はどちらもインデックス作成に適していません。

これをより効率的にする必要がある場合'mon','tue','wed'は、最初に文字列などを保存するのではなく、関連する平日の値を保存することをお勧めします。詳細DAYOFWEEK()については、を参照してください。

于 2012-12-15T20:14:17.997 に答える