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

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

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

Doctrine 2.0はPHP(5.3.2+)のORMです。Doctrine1.2はActive Recordのパターンを使っているのに対し、Doctrine 2はData Mapperパターンを使います。Doctrineのプロジェクトはデータベースの抽象性とPHPで書かれたORMを扱うためのオープンソースのライブラリとツールの集合です。

MySQL

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

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

10289閲覧

Doctrine 2 で InnerJoin にサブクエリを用いる方法

退会済みユーザー

退会済みユーザー

総合スコア0

Doctrine2

Doctrine 2.0はPHP(5.3.2+)のORMです。Doctrine1.2はActive Recordのパターンを使っているのに対し、Doctrine 2はData Mapperパターンを使います。Doctrineのプロジェクトはデータベースの抽象性とPHPで書かれたORMを扱うためのオープンソースのライブラリとツールの集合です。

MySQL

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

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2016/10/06 07:24

編集2016/10/06 08:27

###Doctrine 2 で下記のSQL文を実現したい。

商品ごとに毎日の売上数が保存されているテーブル

MySQL

1CREATE TABLE IF NOT EXISTS `sales` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `item_id` int(11) NOT NULL, 4 `date` date NOT NULL, 5 `value` int(11) NOT NULL DEFAULT '0', 6 PRIMARY KEY (`id`), 7 UNIQUE(`item_id`, `date`) 8) ENGINE=InnoDB DEFAULT CHARSET=utf8;

任意の日付で参照した時その日付以前の累計値も参照したい。

MySQL

1SET @today = '任意の日付'; 2SELECT 3 a.*, b.`total` 4FROM 5 `sales` a 6INNER JOIN 7 ( 8 SELECT 9 `item_id`, SUM(`value`) AS `total` 10 FROM 11 `sales` 12 WHERE 13 `date` <= @today 14 GROUP BY 15 `item_id` 16 ) b 17ON 18 b.`item_id` = a.`item_id` 19WHERE 20 a.`date` = @today;

###試したこと

PHP

1/** 2 * 3 * @param Doctrine\ORM\EntityManager $em 4 * @param \DateTime $date 5 */ 6 7$qb1 = $em->createQueryBuilder(); 8$qb2 = clone $qb1; 9 10$qb1->from('Application\Entity\Sales', 'a') 11 ->select('a') 12 ->andWhere($qb1->expr()->eq('a.date', ':date')); 13 14$qb2->from('Application\Entity\Sales', 'b') 15 ->select('b.itemId, SUM(b.value) AS total') 16 ->andWhere($qb1->expr()->lte('b.date', ':date')) 17 ->addGroupBy('b.itemId'); 18 19$qb1->addSelect('b.total') 20 ->innerJoin(sprintf('(%s)', $qb2->getDQL()), 'b', Doctrine\ORM\Query\Expr\Join::WITH, $qb1->expr()->eq('b.itemId', 'a.itemId')) 21 ->setParameter('date', $date); 22 23$results = $qb1->getQuery()->getResult();

$qb1, $qb2 を innerJoin する前ソースコードに setParameter を設定して結果を確認すると問題はないので Entity には問題ないです。
エラーメッセージが出力しているクエリ文は理想に近い形なのですが
innerJoin にサブクエリは使えないのでしょうか?
または他のやり方があるのでしょうか?

###発生している問題・エラーメッセージ

Additional information: Doctrine\ORM\Query\QueryException File: /vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php:63 Message: [Semantical Error] line 0, col 69 near '(SELECT b.itemId,': Error: Class '(' is not defined. Previous exceptions: Doctrine\ORM\Query\QueryException File: /vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php:41 Message: SELECT a, b.total FROM Application\Entity\Sales a INNER JOIN (SELECT b.itemId, SUM(b.value) AS total FROM Application\Entity\Sales b WHERE b.date <= :date GROUP BY b.itemId) b WITH b.itemId = a.itemId WHERE a.date = :date

###解決した記述

php

1$qb1 = $em->createQueryBuilder(); 2$qb2 = clone $qb1; 3 4$qb2->from('Application\Entity\Sales', 'b') 5 ->select('SUM(b.value)') 6 ->andWhere($qb2->expr()->lte('b.date', ':date')) 7 ->andWhere($qb2->expr()->eq('b.itemId', 'a.itemId')); 8 9$qb1->from('Application\Entity\Sales', 'a') 10 ->select('a') 11 ->addSelect(sprintf('(%s) AS total', $qb2->getDQL())) 12 ->andWhere($qb1->expr()->eq('a.date', ':date')) 13 ->setParameter('date', $date); 14 15$results = $qb1->getQuery()->getResult();

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

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

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

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

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

guest

回答2

0

ベストアンサー

以下で行けると思います。

SQL

1SELECT 2 * 3 , (SELECT SUM(value) 4 FROM sales b 5 WHERE date <= @today 6 AND b.item_id = a.item_id) as total 7FROM sales a where date = @today;

投稿2016/10/06 07:56

kantomi

総合スコア295

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

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

退会済みユーザー

退会済みユーザー

2016/10/06 07:58

解答ありがとうございます。 早速Doctrineに書き直してやってみます。
退会済みユーザー

退会済みユーザー

2016/10/06 08:19

ありがとうございました。 無事にDoctrineで書き直すことができました。
guest

0

例示がないので正確に何をしたいのかわかりませんが

SQL

1SET @today = '任意の日付'; 2select *,(select sum(value*(date<@today)) from sales) as sum 3from sales where date=@today; 4

追記

SQL

1set @today:='任意の日付'; 2select t1.id,t1.item_id,t1.date,t1.value,t2.shokei,t3.gokei 3from sales t1 4inner join (select item_id,sum(value) as shokei from sales where date<@today group by item_id) as t2 on t1.item_id=t2.item_id 5inner join (select sum(value) as gokei from sales where date<@today) as t3 on 1 6where date=@today

投稿2016/10/06 07:36

編集2016/10/06 07:54
yambejp

総合スコア114769

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

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

退会済みユーザー

退会済みユーザー

2016/10/06 07:40

解答ありがとうございます。 任意の日付で参照した時その日付以前の累計値も参照したいのです。 このSQL文でDoctrineに書き直してやってみます。
yambejp

2016/10/06 07:43

>任意の日付で参照した時その日付以前の累計値も参照したい それはよくわかります。 今回とくにわからなかったのは ・item_id毎にしなくてもいいのか? ・当日のデータは集計しなくてもいいのか? ということです。 単に指定日以前のデータをまるっと合計していいなら提示したソースでいけると思います
退会済みユーザー

退会済みユーザー

2016/10/06 07:45

item_id毎検索した日付も集計したいと思っております。
yambejp

2016/10/06 07:55

一応item_idごとの小計と全体の合計を追記しておきました
退会済みユーザー

退会済みユーザー

2016/10/06 07:58

ありがとうございます。 ですがいま問題としているのはSQL文ではなくて Doctrine 2 で InnerJoin にサブクエリを用いる方法なので join 区の中にサブクエリを用いない方法のSQL文なのならば書き換えられると思います。
yambejp

2016/10/06 08:04

Doctrine 2への知識が不足しているので明確な解決策は提示できませんが >join 区の中にサブクエリを用いない方法 を前提とするなら、もし複数SQLを連続して発行できるなら サブクエリの部分をテンポラリテーブルに流し込んで 結合する手もあるかと思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問