質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

3回答

1600閲覧

別テーブルから出てきた検索結果を用いて別のテーブルにinsertしたい

miya71ma

総合スコア49

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

0クリップ

投稿2019/06/20 01:30

編集2019/06/20 03:25

#システム概要
csvで株価一覧をダウンロードしてくる(人が作業)
phpのページを使ってDBにインサートする

php別ページで条件に合う株銘柄があるかを検索したい
その際に検索条件が4日間"today_close "-"today_open ">0のものとしたい
この場合SQLで別テーブルに4日連続"today_close "-"today_open ">0であるかどうかをbooleanで入れておいて検索時にそちらを参照する形がいいと思っているのですがそれができずに困っています

php

1<?php 2/* HTML特殊文字をエスケープする関数 */ 3function h($str) { 4 return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); 5} 6$double_array = [6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24]; 7// パラメータを正しい構造で受け取った時のみ実行 8if (isset($_FILES['upfile']['error']) && is_int($_FILES['upfile']['error'])) { 9 try { 10 /* ファイルアップロードエラーチェック */ 11 switch ($_FILES['upfile']['error']) { 12 case UPLOAD_ERR_OK: 13 // エラー無し 14 break; 15 case UPLOAD_ERR_NO_FILE: 16 // ファイル未選択 17 throw new RuntimeException('File is not selected'); 18 case UPLOAD_ERR_INI_SIZE: 19 case UPLOAD_ERR_FORM_SIZE: 20 // 許可サイズを超過 21 throw new RuntimeException('File is too large'); 22 default: 23 throw new RuntimeException('Unknown error'); 24 } 25 $tmp_name = $_FILES['upfile']['tmp_name']; 26 $detect_order = 'ASCII,JIS,UTF-8,CP51932,SJIS-win'; 27 setlocale(LC_ALL, 'ja_JP.UTF-8'); 28 /* 文字コードを変換してファイルを置換 */ 29 $buffer = file_get_contents($tmp_name); 30 if (!$encoding = mb_detect_encoding($buffer, $detect_order, true)) { 31 // 文字コードの自動判定に失敗 32 unset($buffer); 33 throw new RuntimeException('Character set detection failed'); 34 } 35 file_put_contents($tmp_name, mb_convert_encoding($buffer, 'UTF-8', $encoding)); 36 unset($buffer); 37 /* データベースに接続 */ 38 $pdo = new PDO( 39 'mysql:dbname=DB名;host=localhost;charset=UTF8', 40 'root', 41 '', 42 array( 43 // カラム型に合わない値がINSERTされようとしたときSQLエラーとする 44 PDO::MYSQL_ATTR_INIT_COMMAND => "SET SESSION sql_mode='TRADITIONAL'", 45 // SQLエラー発生時にPDOExceptionをスローさせる 46 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 47 // プリペアドステートメントのエミュレーションを無効化する 48 PDO::ATTR_EMULATE_PREPARES => false, 49 ) 50 ); 51 52 $stmt = $pdo->prepare('INSERT INTO tableA VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); 53 /* トランザクション処理 */ 54 $pdo->beginTransaction(); 55 try { 56 $fp = fopen($tmp_name, 'rb'); 57 while (($row = fgetcsv($fp)) !== FALSE) { 58 if ($row === array(null)) { 59 // 空行はスキップ 60 continue; 61 } 62 //print_r($row[1]); 63 /*ここに"-"が格納されていた場合の処理を記載する*/ 64 for($i = 0; $i < 25; $i++){ 65 if(strcmp($row[$i],'-') == 0){ 66 //var_dump($row[1]); 67 $st = $pdo->prepare('SELECT * FROM tableA where SC = ? ORDER BY date DESC LIMIT 1'); 68 69 if($st->rowCount() === 0){ 70 if(in_array($i,$double_array)){ 71 $row[$i]=0; 72 //var_dump($row[$i]); 73 }else{ 74 $row[$i]=NULL; 75 //var_dump($row[$i]); 76 } 77 }else{ 78 while($ro = $st -> fetch(PDO::FETCH_ASSOC)){ 79 //一日前のデータを入れる 80 } 81 } 82 83 }else{ 84 //var_dump($row[$i]); 85 } 86 } 87 if (count($row) > 10000) { 88 // カラム数が異なる無効なフォーマット 89 throw new RuntimeException('Invalid column detected'); 90 } 91 $executed = $stmt->execute($row); 92 } 93 if (!feof($fp)) { 94 // ファイルポインタが終端に達していなければエラー 95 throw new RuntimeException('CSV parsing error'); 96 } 97 fclose($fp); 98 $pdo->commit(); 99 } catch (Exception $e) { 100 fclose($fp); 101 $pdo->rollBack(); 102 throw $e; 103 } 104 /* 結果メッセージをセット */ 105 if (isset($executed)) { 106 // 1回以上実行された 107 $msg = array('green', 'Import successful'); 108 } else { 109 // 1回も実行されなかった 110 $msg = array('black', 'There were nothing to import'); 111 } 112 } catch (Exception $e) { 113 /* エラーメッセージをセット */ 114 $msg = array('red', $e->getMessage()); 115 } 116} 117// XHTMLとしてブラウザに認識させる 118// (IE8以下はサポート対象外w) 119header('Content-Type: application/xhtml+xml; charset=utf-8'); 120?> 121<!DOCTYPE html> 122<html xmlns="http://www.w3.org/1999/xhtml"> 123<head> 124 <title>CSV to MySQL importation test</title> 125</head> 126<body> 127<?php if (isset($msg)): ?> 128 <fieldset> 129 <legend>Result</legend> 130 <span style="color:<?=h($msg[0])?>;"><?=h($msg[1])?></span> 131 </fieldset> 132<?php endif; ?> 133 <form enctype="multipart/form-data" method="post" action=""> 134 <fieldset> 135 <legend>Select File</legend> 136 Filename(CSV is only supported): <input type="file" name="upfile" /><br /> 137 <input type="submit" value="Upload" /> 138 </fieldset> 139 </form> 140</body> 141</html>

MySQL

1CREATE TABLE tableA( 2 SC int(4) NOT NULL "証券コード", 3 name varchar(32) NOT NULL "会社名", 4 market varchar(16) NOT NULL "市場", 5 industry varchar(16) NOT NULL "産業", 6 date datetime NOT NULL "日にち", 7 today_close double "当日終値", 8 the_day_before_ratio double "前日との幅", 9 the_day_before_ratio_per double "前日幅%", 10 ago_close double "前日終値", 11 today_open double "始値", 12 today_high double "高値", 13 today_low double "安値", 14 vwap double "vwap", 15 volume double "出来高", 16 volume_per double "出来高%", 17 trading_value double "売買代金", 18 market_capitalization double "時価総額", 19 price_range_low_limit double "値幅下限", 20 price_range_high_limit double "値幅上限", 21 high_date datetime "高値日", 22 year_to_date_high_price double "年初来高値", 23 year_to_date_high_price_deviation_rate double "年初来高値乖離", 24 low_date datetime "安値日", 25 year_to_date_low_price double "年初来安値", 26 year_to_date_low_price_deviation_rate double "年初来安値乖離" 27);

##やったこと

mySQL

1delimiter // 2CREATE PROCEDURE white() 3BEGIN 4 DECLARE @count INT 5 SET @count = 1000 6 7 WHILE (@count < 9999) 8 SELECT today_close-ago_close into @is_white WHERE SC = @count ORDER BY date DESC LIMIT 4 9 CASE 10 WHEN @is_white>0 THEN INSERT INTO tableB (SC,is_white) VALUES (@count,true) ON DUPLICATE KEY UPDATE @is_white = true 11 WHEN @is_white<=0 THEN INSERT INTO tableB (SC,is_white) VALUES (@count,false) ON DUPLICATE KEY UPDATE @is_white = false 12 END 13END 14CALL white(); 15delimiter;

##エラー
`1064 - SQL構文エラーです。バージョンに対応するマニュアルを参照して正しい構文を確認してください。 : '@is_white double
DECLARE @counter INT
SET @counter =0

WHILE(@coun' 付近 3 行目`

##やりたいこと
tableA

SCtoday_closeago_closedate
1000100942019/06/20/15:00
20001501792019/06/20/15:00
30003473442019/06/20/15:00
100093882019/06/19/15:00
20001791752019/06/19/15:00
30003473412019/06/19/15:00
100086742019/06/18/15:00
20001731602019/06/18/15:00
30003443212019/06/18/15:00
100077712019/06/17/15:00
20001601642019/06/17/15:00
30003403002019/06/17/15:00

のようにデータがtableAに格納されていて
SC=1000はtoday_close-ago_close>0が1720日において全てtrue
SC=2000はtoday_close-ago_close>0が17
20日において一部false
SC=3000はtoday_close-ago_close>0が17~20日において全てtrue

なので
tableB

SCis_whitedate
1000true2019/06/20/15:00
2000false2019/06/20/15:00
3000true2019/06/20/15:00

としたいです

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

構文的に間違えているというエラーです。

それを解消してからの話だと思えます。

valuesで指定するなら変数か値です。変数の場合は@変数名としてしなければなりません。
いきなり**VALUES (SC,true)**だとSCの参照先などはないのですからエラーでしょうね。
やるなら、**VALUES (@count,true)**だと思いますけど。

また、SELECT の結果を変数に代入したいなら

SQL

1select today_close-today_open into @is_white

先ずは基本的なところを押さえてからですね。

また、selectの結果についての処理をループで行いたいなら、カーソル使うのが一般的です。

質問の内容だけなら、insert into select 構文でループなど使用せずにSQL1文で可能だと思いますが。

投稿2019/06/20 02:43

編集2019/06/20 05:29
sazi

総合スコア25138

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

miya71ma

2019/06/20 03:03

ご指摘後最もでした...ですが'SET @count = 1000' にエラーが出てるんですよね...
sazi

2019/06/20 03:30 編集

どのようなエラーですか?
miya71ma

2019/06/20 03:36

1064 - SQL構文エラーです。バージョンに対応するマニュアルを参照して正しい構文を確認してください。 : '@is_white double DECLARE @counter INT SET @counter =0 WHILE(@coun' 付近 3 行目` と出ています
sazi

2019/06/20 03:40

DECLAREの前で変数宣言しているから。 マニュアル読む癖付けないと駄目ですよ。
guest

0

ベストアンサー

ある基準日から過去4日間の全てが today_close > today_open であるような銘柄、ですよね。
today_close > today_open であり、日付が日付1~日付2(4日間。ただし営業日で換算しないとダメ)の間にあるデータを探し、その個数が 4 であるもののみを抽出すればよい、のかな……

SELECT sc FROM tableA WHERE today_close > today_open AND date between 日付1 AND 日付2 GROUP BY sc HAVING count(*) = 4

で対象の sc が取れますけど、これではダメですかね?

※この方式なら、「何日間」を可変にできますね

投稿2019/06/20 02:26

編集2019/06/20 02:37
tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

miya71ma

2019/06/20 03:04

これで取得できましたがfor文で回すなどどうすればいいのでしょうか...
tacsheaven

2019/06/20 04:05

検索が一発でできるので、tableB は不要になります。ですのでこの結果を php の別ページで使いたければ、PHP からこの SQL を投げて結果を fetch すればよいのでは?
miya71ma

2019/06/20 04:11

確かにその通りですね!ほかにも検索条件があってこうしなきゃと頭固くなってました!試行錯誤してみます!ありがとうございます
guest

0

もっと問題点を絞り込んで質問したほうがよいでしょう

・4日間"today_close "-"today_open ">0の銘柄を拾うという命題ですね?

today_openと前日のtoday_closeは一緒なのでしょうか?
today_openが前日のtoday_closeより100円高く、当日50円しか下がらなければ
昨日よりは値上がりした銘柄になり、4日続落とはなりませんが大丈夫ですか?

また基準日を指定する必要があると思うのですが、

  • 4日さかのぼるのか
  • 4日後までなのか
  • 基準日を含む4日間なのか

などイメージがわきません

ざっくりいらないデータを削って

SQL

1CREATE TABLE tbl( 2SC int(4) NOT NULL, 3`date` datetime NOT NULL, 4today_close double, 5today_open double);

に対して、2~3社、1週間分程度サンプルをあげてどこをどうひっかけたいか例示されるとよいでしょう

追記

連続性についてはロジックがかなり煩雑になるので
期間を入れることで対応してください
以下サンプル

  • 元データ

SQL

1CREATE TABLE tbl( 2SC int(4) NOT NULL, 3today_close double, 4today_open double, 5`date` datetime NOT NULL 6); 7 8insert into tbl values 9(1000,100,94,'2019-06-20 15:00'), 10(2000,150,179,'2019-06-20 15:00'), 11(3000,347,344,'2019-06-20 15:00'), 12(1000,93,88,'2019-06-19 15:00'), 13(2000,179,175,'2019-06-19 15:00'), 14(3000,347,341,'2019-06-19 15:00'), 15(1000,86,74,'2019-06-18 15:00'), 16(2000,173,160,'2019-06-18 15:00'), 17(3000,344,321,'2019-06-18 15:00'), 18(1000,77,71,'2019-06-17 15:00'), 19(2000,160,164,'2019-06-17 15:00'), 20(3000,340,300,'2019-06-17 15:00'); 21
  • 検索

SQL

1select sc 2,group_concat(today_close order by date desc)=group_concat(today_close order by today_close desc) as is_down 3,max(date) as date 4from tbl 5where `date` between '2019-06-17 00:00:00' and '2019-06-20 23:59:59' 6group by sc

※注意:datetimeのbetweenは00:00:00~23:59:59を指定すること

投稿2019/06/20 01:48

編集2019/06/20 04:22
yambejp

総合スコア114583

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

miya71ma

2019/06/20 01:59

すみません... >>today_openと前日のtoday_closeは一緒なのでしょうか?   いいえ、異なる場合があるので検索結果は4日+1である必要があると思っていましたが続落かどうかの判定は確かにおっしゃる通りなので質問文を訂正させていただきます
yambejp

2019/06/20 04:23

追記しておきました group_concatの裏技みたいな感じで処理するとよいでしょう
miya71ma

2019/06/20 05:25

ありがとうございます! 初めてみたので調べてかみ砕いてみます..
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問