たとえば以下のようなteamtblテーブルで
チームに所属する人物をカンマ区切りでnameに登録してある場合

id | team | name
------------------------------------
1 | teamA | yamada,kobayasi,hayasi
2 | teamB | kobayasi,takizawa,komori
3 | teamC | takizawa,moriyama
4 | teamD | mori,yamada,kobayasi


「mori」さんが所属するチームのSELECTはどのようにしたらよいでしょうか?

SELECT * FROM teamtbl WHERE name LIKE '%mori%'

とした場合、「komori」「moriyama」がいるteamB、CまでSELECTされてしまいます。

A 回答 (2件)

yahoo知恵袋でも回答しましたが、テーブル設計に問題があります。


まず、「正規化」を勉強してください。
チームテーブルと選手テーブルテーブルを分ければ
select チームテーブル.team
from チームテーブル inner join 選手テーブル
on チームテーブル.team=選手テーブル.team
where 選手テーブル.name='mori'
で行けます。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
既存のシステムなのでテーブル変更は不可能なのです。
今年から業務を引き継ぎ、テーブル設計に問題があるのは承知しています;;

いろいろ調べてみて、以下のような書き方にたどり着きましたが
どうでしょう?

SELECT * FROM teamtbl WHERE string_to_array(name,',') && ARRAY['mori']

お礼日時:2011/07/20 17:53

違ったら申し訳ありません。



単純に検索条件にカンマを含めて

SELECT * FROM teamtbl WHERE name LIKE '%mori,%'

ではSELECTできませんでしたか?
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

4 | teamD | yamada,kobayasi,mori

となる場合、SELECTされなくなってしまいます><

お礼日時:2011/07/20 17:00

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す

このQ&Aと関連する良く見られている質問

Q配列に指定した値が含まれているものを抽出する方法

こんにちは。
いつもお世話になっております。

SQLにて、配列のフィールドに指定した値が含まれているものを抽出する方法を質問致します。


SQLのテーブル(テーブル名:data)に配列のフィールド(フィールド名:array[])があるとします。
Array[]フィールドの中に、1, 2, 6のいずれかが含まれている場合表示対象となるSQL文を書くには、どのように書けばよいですか。PostgreでSQL文を書くとします。


実現したい動作は以下の通りです。
array[] の値
{1,3,5} 表示対象になる
{3,8,9,10}  表示対象にならない
{2,6} 表示対象になる

以上よろしくお願い致します。


ちなみに、array[]フィールドの中に、2(指定した数値が1つだけ)を探すとき、
select * from data where 2=any (array);
とすればいいことは確認できました。

Aベストアンサー

&& 演算子 (重複する, 共通要素を持つ) を使います。

SELECT * FROM (VALUES
(ARRAY[1,3,5]),
(ARRAY[3,8,9,10]),
(ARRAY[2,6])
) T(arr)
WHERE ARRAY[1,2,6] && arr;

参考URL:http://www.postgresql.jp/document/current/html/functions-array.html

Qカンマ区切りで格納するカラムって設計上ありでしょうか?

例えば、1,2,5,8,9,10
というような形でデータを格納するカラムをテーブルに作ろうと思っているのですが設計上ありでしょうか?
格納したあとは、それSELECTのIN(1,2,5,8,9,10)で
使用するのが主で、更新時のキーが別にあればOKという感じでしょうか?
こういう場合に、このような設計をした事があるよ。いった例など教えていただけると幸いです。

Aベストアンサー

「設計上あり」とは、CSV入出力を考慮しての事でしょうか?

データベースソフトでは、テキスト入出力をする場合に区切り文字をデフォルトの「,」以外にもタブとか任意の文字に設定できることが多いので、その意味では「あり」です。Mysql、firebird、ACCESS、桐いずれもOKです。

あと「更新時のキーが別に云々」のところもよく意味がわからないのですが...

学術的意味合いで「データベースとはかくあるべき」というのがあるのかどうかは知りませんが。

Q複数の条件での絞り込み検索の仕方

PostgreSQLで複数の条件での絞り込み検索をしたいのです。

テーブルには
発売日、商品名、入荷日
があります。
例えば
発売日が2007年5月1日から5月5日で、商品名に「○○」もしくは「××」もしくは「△△」が含まれており、入荷日が一番新しいもの
という条件で検索したいのです。

発売日だけの絞込みならBetweenですし、商品名だけならor、入荷日の最新だったらmaxを使えば個別には検索できるのですが、これをまとめて一行でやるにはどうしたらよいのかわかりません。
それぞれでandでつなげてみましたが、orの条件がうまく反映されず、一個目の○○だけが検索に引っかかってる状態です。
××や△△もひっかかるようにするにはどう記述したらよいのでしょうか。

Aベストアンサー

データ件数がどのくらいあるのかは分かりませんが、ユニークなキーもなく、likeの任意一致をorでつなぐという方法は、性能を出せませんよ?

select *
from t1
where 入荷日 in(
select max(入荷日)
from t1
where 発売日 between '2007-05-01' and '2007-05-05'
and (商品名 like '%○○%' or 商品名 like '%××%' or 商品名 like '%△△%')
)
and 発売日 between '2007-05-01' and '2007-05-05'
and (商品名 like '%○○%' or 商品名 like '%××%' or 商品名 like '%△△%')

Q複数行の結果を単一列に連結

以下のような【TABLE1】と【TABLE2】をID_SUBの列で結合した結果を
【A.結果】のように取得したいのですがうまくいきません。

【TABLE1】
ID ID_SUB
1 A1
2 B1

【TABLE2】
ID ID_SUB ID_SUB_CODE
1 A1 AAA1
2 A1 AAA2
3 B1 BBB1
4 B1 BBB2

【A.結果】
ID_SUB ID_SUB_CODE
A1 "AAA1,AAA2"
B1 "BBB1,BBB2"

いろいろ調べたのですが、MySQLにはGROUP_CONCATの
関数を使うと簡単に出来るみたいですが、PostgreSQLには
似たような関数がなく、ARRAYが使えるかな?と思ってためしてみましたが

array_to_string(ARRAY(ID_SUB_CODE, ','))

等のような感じで試した結果、ID_SUB_CODEが
全て連結されるような使い方しか出来ませんでした。

A1 "AAA1,AAA2,BBB1,BBB2"
B1 "AAA1,AAA2,BBB1,BBB2"

何か良い方法はありますでしょうか?

以下のような【TABLE1】と【TABLE2】をID_SUBの列で結合した結果を
【A.結果】のように取得したいのですがうまくいきません。

【TABLE1】
ID ID_SUB
1 A1
2 B1

【TABLE2】
ID ID_SUB ID_SUB_CODE
1 A1 AAA1
2 A1 AAA2
3 B1 BBB1
4 B1 BBB2

【A.結果】
ID_SUB ID_SUB_CODE
A1 "AAA1,AAA2"
B1 "BBB1,BBB2"

いろいろ調べたのですが、MySQLにはGROUP_CONCATの
関数を使うと簡単に出来るみたいですが、PostgreSQLには
似たような関数がなく、ARRAYが使え...続きを読む

Aベストアンサー

select id_sub,
( select array_to_string(ARRAY(select id_sub_code from table2
where table1.id_sub=table2.id_sub ), ',') )
from table1;

なんて参考になりませんか。

QCSVファイルの中で、「 , 」カンマを使いたい

「 , 」で区切られたCSVファイルの中で、「 , 」カンマを使いたいのですが、可能でしょうか?

具体的には「これは1,500円でした。」というように、CSVファイルに収められた文章内で出てくる半角の数字(お金)の区切りに使いたいのです。
全角では代用したくないのですが、CSVファイルでデータを受け渡しする際に、困っています。

例えば、特殊文字などで対応可能でしょうか?

Aベストアンサー

受け渡しに使うと言うことは相手方のアプリケーションのことも考えなければいけないのですが・・・とりあえず対応が簡単そうな方法を。

1.各セルを""で囲む。(もちろんデータにダブルクォートがある場合はカンマと同様に困ります。
2.カンマで区切らずにタブで区切る。(比較的使われない文字ですが、やはりデータ中にタブがあるとカンマと同様です)

難しいけれど完璧に対応するためには、データ中の区切り文字は特殊な文字列に変更し、受け取り側のアプリケーションではその特殊な文字列をデータ中の区切り文字として扱うという方法が使われます。
例えば、データ中のカンマは\,にするとか。

データ作成側、受け取り側でそれぞれどこまで対応できるのか分かるともっと簡単かつ具体的な方法を回答できるかも知れません。

Qcastの使用法について(初心者です)

始めまして。初心者ですので基本的な質問になるかもしれませんがよろしくお願いします!

なぜかPostgreSQLを仕事に使うことになり、四苦八苦しています。

テーブルを作成しているときに、
create table syouhin (shinamono text, nedan int);
とするとします。
で、insert でデータを入れていきますが、
例:
shinamono | nedan
------------------
みかん |100
マンゴー |200

例えば、nedan のcast が今、int にしましたが、これをchar やfloatに変えたいときはどうすればよろしいのでしょうか?

どなたか御存じの方、お手数ですがお教え下さい!!!

Aベストアンサー

CAST関数の文法は、CAST(○ AS △) となります。
○:変換する値
△:変換する型

Select CAST(nedan AS char(10)) ~
とすればできると思いますよ

QSQL文について(片方のテーブルに存在しないレコード抽出)

以下のような2つのテーブルがあったとして、
2つともに存在する「店コード」を抽出するのはSQLは分かるのですが、
片方に存在しない「店コード」(以下の例の場合、「2」)を抽出するSQLを
一文で書くにはどうすればいいのでしょうか?

<店テーブル>
店コード住所・・・(その他、基本情報)
1aaa
2bbb
3ccc

<販売テーブル>
店コード販売品目・・・(その他、販売数など)
1xxx
3zzz

Aベストアンサー

オプティマイザ次第だけど、NOT-INは、あまりお勧めでない。
外部結合も索引があっても有効に使われないので、お勧めでない。

select * from A where not exists(select 1 from B where A.店コード=B.店コード);

Qdate型でのbetweenについて教えてください。

皆様、新年明けましておめでとうございます。

早速ですが、date型でのbetweenについて教えてください。

SQL文
SELECT * FROM test WHERE date between date '2007-12-01' and date '2007-12-31'

を発行すると、2007-12-31のレコードがあるのに該当しません・・・

試しにSQL文を
SELECT * FROM test WHERE date between date '2007-12-01 00:00:00' and date '2007-12-31 23:59:59'
としても2007-12-31のレコードは検索されません・・・
SQL文を
SELECT * FROM test WHERE date between date '2007-12-01' and date '2008-01-01'
にすると2007-12-31が該当するのですが、
SELECT * FROM test WHERE date between date '2007-12-01' and date '2007-12-31'
では2007-12-31のレコードは該当しないものでしょうか??

select * from test where num between 10 and 100
とした場合では、num が 10 ~ 100 のものが問い合わされますよね??
date型になるとこうならないのでしょうか??

よろしくお願いします。

皆様、新年明けましておめでとうございます。

早速ですが、date型でのbetweenについて教えてください。

SQL文
SELECT * FROM test WHERE date between date '2007-12-01' and date '2007-12-31'

を発行すると、2007-12-31のレコードがあるのに該当しません・・・

試しにSQL文を
SELECT * FROM test WHERE date between date '2007-12-01 00:00:00' and date '2007-12-31 23:59:59'
としても2007-12-31のレコードは検索されません・・・
SQL文を
SELECT * FROM test WHERE date between date...続きを読む

Aベストアンサー

No.1です。
列の属性をtimestampにして実行してみました。

Welcome to psql 8.2.0, the PostgreSQL interactive terminal.
farm=# create table testtbl6 (hoge timestamp);
CREATE TABLE
farm=# insert into testtbl6 values('2007-12-31');
INSERT 0 1
farm=# select * from testtbl6;
hoge
---------------------
2007-12-31 00:00:00
(1 row)

farm=# select * from testtbl6 where hoge between '2007-01-01' and '2007-12-31';
hoge
---------------------
2007-12-31 00:00:00
(1 row)

farm=# select * from testtbl6 where hoge between date '2007-01-01' and date '2007-12-31';
hoge
---------------------
2007-12-31 00:00:00
(1 row)

●時間だけを多少進めたデータを追加してみました

farm=# insert into testtbl6 values('2007-12-31 01:00:00');
INSERT 0 1
farm=# select * from testtbl6;
hoge
---------------------
2007-12-31 00:00:00
2007-12-31 01:00:00
(2 rows)

farm=# select * from testtbl6 where hoge between '2007-01-01' and '2007-12-31';
hoge
---------------------
2007-12-31 00:00:00
(1 row)

farm=# select * from testtbl6 where hoge between date '2007-01-01' and date '200
7-12-31';
hoge
---------------------
2007-12-31 00:00:00
(1 row)

よって、あなたのDBに登録してあるデータは、2007-12-31と午前0時を少し回っているデータが登録されているため、
検索でヒットしないのではないのでしょうか?

No.1です。
列の属性をtimestampにして実行してみました。

Welcome to psql 8.2.0, the PostgreSQL interactive terminal.
farm=# create table testtbl6 (hoge timestamp);
CREATE TABLE
farm=# insert into testtbl6 values('2007-12-31');
INSERT 0 1
farm=# select * from testtbl6;
hoge
---------------------
2007-12-31 00:00:00
(1 row)

farm=# select * from testtbl6 where hoge between '2007-01-01' and '2007-12-31';
hoge
---------------------
2007-12-31 ...続きを読む

Qテーブルからのselectにおいてデータの有無により結果をわけたい

id | point
----+-------
1 | 10
2 | 9
3 | 5
....
というテーブルがあるとします.
idを指定してpointを得たいのですが、そのidがこのテーブルに存在しない場合は空の結果ではなく0を返したいのです.
plpgsqlなどを使いif文で場合分けすればできることはわかっているのですがSQL文だけで(それもできれば1文で)これを実現する方法はあるでしょうか?
よろしくお願い致します。

Aベストアンサー

変則的ですが、これでよければidがユニークでなくても大丈夫ですし、集合関数を使わなくてもOKです。

select dm.id,case when ex1.point is null then 0 else ex1.point end from
(select ? as id) as dm left join ex1 on dm.id = ex1.id;

?を適当に変えてください。
chukenkenkouさんの発想はこれですよね。

QpostgreSQLで更新後のデータを取得したい。

postgreSQLで更新後のデータを取得したい。

初めて質問させていただきます。

postgreSQLでupdateした後、更新後のデータをselectで取得したいのですが、
トランザクションが完了するまでにselect文が発行されているみたいで、更新前のデータを取得してしまいます。

それぞれ、違うファイルから投げられているので、同じトランザクションにすることはできません。

何かいい方法があればご教授お願いします。


a.phpで下記のSQLを発行

update
test_tbl
set
test1 = 'aaa'
where
test2 = 'bbb'

a.phpが走っている間に、下記のb.phpが実行される。

select
test1
from
test_tbl

環境
php5
postgres8.1

Aベストアンサー

2個提案します。

1.Aでupdateする前にcvs形式でファイル保存して、Bではselectせずにcvsを見に行く。

ただ、1レコードならいいですけど、膨大なレコードの場合
考え物だと思います。

2.Bでselectする時にFOR UPDATEをつければAが更新中だったら
更新が終わるのを待ってからselect出来ると思います。

ただ、Aが数秒おきに行われるということなので、
Bのselectが終わったらすぐにロックを解除しないとAが数秒間
止まる可能性を考えなければなりません。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報