• 締切済み

POSTGRESでMYSQLと同じ結果を得る方法

create table test (a varchar(10), b varchar(10)); insert into test values ('a','a'); insert into test values ('b','b'); insert into test values ('b','c'); insert into test values ('c','d'); select count(*), a, b from test group by a; 上記を実行するとMYSQLでは +----------+------+------+ | count(*) | a | b | +----------+------+------+ | 1 | a | a | | 2 | b | b | | 1 | c | d | +----------+------+------+ という結果になる。 POSTGRESでは以下のエラーになります。 ERROR: column "test.b" must appear in the GROUP BY clause or be used in an aggr egate function select count(*), a, b from test group by a, b; とすると結果が変わってしまいます。 MYSQLと同じ結果をPOSTGRESで得るいい方法はありますか?

みんなの回答

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.1

まずMySQLの「GROUP BYで指定されていない項目を集計関数なしに指定できる」というのがSQLの規格から外れていることを認識してください。 その上で http://postoro.blogspot.com/2011/03/mysql-group-by-select.html にありますけれど、どの行の値が使われるかは保証されません。 もし、MySQLの項目で最小値を表示したいということなら select count(*), a, min(b) from test group by a; にすればMySQL、PostgreSQLともに同一の結果を取得できます。

関連するQ&A

  • 測定結果が決められた範囲内か判定するSQL文

    決められた範囲内に測定結果が入っているかを判定するSQL文(またはストアドプロシージャ)を PostgreSQL 14.0を使って作ろうとしていますが、正しい結果が得られません。 具体的には、ケーブル・テーブルとスペック・テーブルで一致するテスト項目同士(例えば、'Test_1'同士)だけを比較したいのですが、他のテスト項目も引っ掛けてしまいます。 あと、下記のwhere test_item = 'Test_1', 'Test_2', 'Test_3'の部分を select test_item from cable; から一つ一つ取り出してループで回して代入し、最終的には id | test_item | test ----+-----------+------ 1 | Test_1 | 1.5 2 | Test_1 | 1.8 2 | Test_2 | 2.5 という、まとまった出力を得たいのですが、その方法を教えていただけないでしょうか? 自作のテーブルとSQL文は以下になります: create table cable( id integer default 0 not null ,test_item varchar(30) not null ,test numeric(3, 1) ,primary key (id, test_item) ); insert into cable values(1, 'Test_1', 1.5); insert into cable values(1, 'Test_2', 4.5); insert into cable values(1, 'Test_3', 2.5); insert into cable values(2, 'Test_1', 1.8); insert into cable values(2, 'Test_2', 2.5); insert into cable values(3, 'Test_3', 2.5); create table spec( test_item varchar(30) not null , lower_spec numeric(3, 1) , upper_spec numeric(3, 1) , primary key(test_item) ); insert into spec values('Test_1', 1.0, 2.0); insert into spec values('Test_2', 2.0, 3.0); insert into spec values('Test_3', 3.0, 4.0); postgres=# select * from cable c WHERE c.test_item = test_item and test < (select upper_spec from spec where test_item = 'Test_1') and test > (select lower_spec from spec where test_item = 'Test_1'); id | test_item | test ----+-----------+------ 1 | Test_1 | 1.5 2 | Test_1 | 1.8 (2 行) postgres=# select * from cable c WHERE c.test_item = test_item and test < (select upper_spec from spec where test_item = 'Test_2') and test > (select lower_spec from spec where test_item = 'Test_2'); id | test_item | test ----+-----------+------ 1 | Test_3 | 2.5 ←'Test_3'なので引っ掛けたくない 2 | Test_2 | 2.5 3 | Test_3 | 2.5 ←'Test_3'なので引っ掛けたくない (3 行) postgres=# select * from cable c WHERE c.test_item = test_item and test < (select upper_spec from spec where test_item = 'Test_3') and test > (select lower_spec from spec where test_item = 'Test_3'); id | test_item | test ----+-----------+------ (0 行) 必要であれば補足します。 では、よろしくお願いします。

  • MySQLから取り出したものを3つに分ける

    MySQLに以下のようなSQLを打ちました。 create table table_list( id int, task varchar(255) ); insert into table_list values(1,'ほげほげ1-1'); insert into table_list values(1,'ほげほげ1-2'); insert into table_list values(2,'ほげほげ2-1); insert into table_list values(2,'ほげほげ2-2'); insert into table_list values(3,'ほげほげ3-1'); そして、空のdiv要素が3つあります。 このデータベースからidの数値別に、div要素へtaskの文字列を入れたいのですが、どうすればいいのでしょうか? SQLで「select * from table_list」をやってからtaskを取り出すのか、3回SQLで「select task from table_list where id=1」のようにするのがよろしいんでしょうか?

    • ベストアンサー
    • PHP
  • Using temporary; Using filesort を回避したい

    はじめまして。よろしくお願いします。 下記の場合、Using temporary; Using filesort を回避するには どうしたらよいでしょうか。 次の 2 つのテーブルがあります。 CREATE TABLE `test1` ( `f1` int(11) NOT NULL, `f2` int(11) NOT NULL, PRIMARY KEY (`f1`,`f2`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `test1` VALUES ('1', '2'); INSERT INTO `test1` VALUES ('1', '3'); INSERT INTO `test1` VALUES ('1', '4'); INSERT INTO `test1` VALUES ('2', '1'); INSERT INTO `test1` VALUES ('2', '3'); CREATE TABLE `test2` ( `f1` int(11) NOT NULL, `f2` varchar(20) default NULL, `f3` varchar(20) default NULL, PRIMARY KEY (`f1`), KEY `ix_f2_f3` (`f2`,`f3`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `test2` VALUES ('1', 'A', 'a'); INSERT INTO `test2` VALUES ('2', 'B', 'b'); INSERT INTO `test2` VALUES ('3', 'C', 'c'); INSERT INTO `test2` VALUES ('4', 'D', 'd'); 次の SELECT を実行すると Using temporary; Using filesort が 現れてしまいます。 explain select test2.f2, test2.f3 from test1, test2 where test1.f1 = 1 and test1.f2 = test2.f1 order by test2.f2, test2.f3; order by ... をなくすと問題ないのですが、ソートは必要です。 複数のキーに対してORDER BYを実行する場合 インデックスを使用できないとあるので ix_f2_f3 は使用されず Using filesort となるのはわかるのですが、 Using temporary となる理由と回避方法がわかりません。 ご教示よろしくおねがいいたします。

  • MySQL初心者

    -mysql CREATE DATABASE testdb; use testdb; CREATE TABLE car_table(id int(10),name varchar(50)); INSERT INTO car_table VALUES (2,'乗用車'); INSERT INTO car_table VALUES (3,'オープンカー'); INSERT INTO car_table VALUES (4,'トラック'); SELECT * FROM car_table; これで間違ってるとは思わないんですが、なぜか ERROR 1049(42000): Unknown database 'testdb・・ とでます。なぜなんでしょうか?全然わかりません。 何かの設定ミスかなにかでしょうか?

    • ベストアンサー
    • MySQL
  • フィールドをデフォルト0にする

    フィールドをデフォルト0にする方法が知りたいです。 以下のようなサンプルがります。 drop table test_a; create table test_a ( name varchar2(10), a number(1), b number(1), c number(1) ) insert into test_a (name) values ('AAA'); insert into test_a (name,a) values ('BBB', NULL); insert into test_a (name,a,b) values ('CCC', NULL,NULL); select * from test_a; この状態では、a,b,cはNULLですが、a,b,cの値をデフォルト値で0にしたい為、 update test_a set a = 0, b = 0, c = 0; として、データを直して、次回から insert into test_a (name) values ('DDD'); とすると、nameがDDDの時もa,b,cが0となるようにテーブル定義を変えたいのですが 既存のテーブルをそのままで、途中から変更する方法が知りたいです。

  • MySQLへのINSERT

    JAVA Connection とPreparedStatement でMysqlへINSERT分を実行したいのですが、エラー が出力されます。 SELECT分だと正常に実行されるのですが。。。。どうしてでしょうか? ps = conn.prepareStatement(\" INSERT INTO test00 (data1) values (1)\")

    • ベストアンサー
    • Java
  • TO_NUMBERの結果は、カラムに追加できない?

    いつもお世話になっています。 TO_NUMBER実行時、結果はnumeric型で取得できると思うのですが、 その値をカラムに追加することはできるのでしょうか? insert into number2 values((select numberStr,TO_NUMBER (numberStr,'000.000') from number),'aaa'); 実行すると、 副問い合わせは1列のみを返さなければなりませんというErrorが生じます。 なのでwhere句を追加しましたが、結果は同じです。 実行したsqlは、 create table number ( count integer not null primary key, numberStr varchar(20) not null ); create table number2 ( no numeric not null primary key, numberS varchar(30) not null); insert into number values(5,'555.55000'); insert into number2 values((select numberStr,TO_NUMBER (numberStr,'000.000') from number where count=5),'aaa'); です。 宜しくお願いします。

  • MySQLに100万件登録する最も効率の良い方法

    A(600)xB(800)xC(3)で144万件の作成してMySQLへ登録したい のですが、最も効率良く登録する方法は何でしょうか? 私がとりあえず思いつくのは、下記2つのうち案2)です。 案1)プログラム&MySQL 1.PHPなどのプログラムのループ処理でテストデータを作成 2.mysql>LOAD DATA INFILE "/path/to/file.csv" INTO TABLE tablename FIELDS TERMINATED BY ","; 懸念点:メモリが足りず小分けにしないとインポートできなそう。 案2)プログラムのみ 1.PHPなどのプログラムのループ処理でテストデータを作成し、   1つのINSERT文で、1000件ぶんを一気にコミット 例:INSERT INTO table (a,b,c) VALUES (1,1,1),(1,1,2)・・・

  • MySQLでWHEN句のサブクエリ中にて

    MySQL ver.5.0.95です。 PHPからSQL文を作ってDBへインサートしているのですが 重複した値が合った場合はupdateするように書いています。 TBL1には |id   |string   |count 1    aaa    0 2    bbb    3 3    ccc    1 TBL2には |id2    |string2    |count2 1      aaa      0 2      bbb      2 3      ccc      1 実際はもう少し複雑ですが、こういう感じでデータが入ってるとします。 このとき、TBL1のそれぞれをインサート若しくはアップデートするのに TBL2の同一IDのものの、count2の状態によって場合分けしたく 同一IDのcount2が1以上なら変更しない、という風にするため以下のように書いたのですが insert into TBL1 values (1, "aaa", 3), (2, "bbb", 3), (3, "ccc", 3), (4, "ddd", 3) on duplicate key update count = CASE WHEN (select count2 from TBL2 where id2 = values(id)) >=1 THEN count ELSE count + values(count) END; #1064 - You have an error in your SQL syntax;というエラーになって出来ません。 WHENの中のサブクエリで、where id2 = values(id) 恐らくこの文がダメなようです。 例えば決め撃ちで1つ1つ書くと通ります。 insert into TBL1 values(1, "aaa", 3) on duplicate key update count = CASE WHEN (select count2 from TBL2 where id2 = 1) >=1 THEN count ELSE count + values(count) END; insert into TBL1 values(2, "bbb", 3) on duplicate key update count = CASE WHEN (select count2 from TBL2 where id2 = 2) >=1 THEN count ELSE count + values(count) END; insert into TBL1 values(3, "ccc", 3) on duplicate key update count = CASE WHEN (select count2 from TBL2 where id2 = 3) >=1 THEN count ELSE count + values(count) END; insert into TBL1 values(4, "ddd", 3) on duplicate key update count = CASE WHEN (select count2 from TBL2 where id2 = 4) >=1 THEN count ELSE count + values(count) END; これをエラーになったような文に変えて1文にまとめたいのですが、無理でしょうか? あとそもそもこれをまとめたほうが速いと思ってそうしたいのですが、 変わらないのなら1文1文;でつなげて書くやり方でいこうと思っています。 まとめると速くなることはあるでしょうか?

    • ベストアンサー
    • MySQL
  • 【MySQL5.7】IDごとの最頻値

    お世話になります。MySQLでidごとの最頻値を抽出しているのですが、 select id, hantei,count(*) as ModeCount from member a group by id,hantei having count(*) >= all(select count(*) from member b where b.id=a.id group by hantei asc) order by id,hantei レコード数は5000件ほどなのですが現在の方法では10.485sと時間がかかりすぎて困っています。MySQLでは最頻値を出すのにサブクエリを使うしかないのでしょうか? こうすればもっと速くなるよって方法があれば教えてください。お願いします。

    • ベストアンサー
    • MySQL