SQL質疑応答スレ 19問目
レス数が1000を超えています。これ以上書き込みはできません。
このスレは
「こういうことをやりたいんだけどSQLでどう書くの?」
「こういうSQLを書いたんだけどうまく動きません><」
などの質問を受け付けるスレです。
SQLという言語はISOによって標準化されていますが
この標準を100%実装したDBMSは存在せず、
また、DBMSによっては標準でない独自の構文が
追加されていることもあります。
質問するときはDBMS名を必ず付記してください。
【質問テンプレ】
・DBMS名とバージョン
・テーブルデータ
・欲しい結果
・説明
前スレ:
SQL質疑応答スレ 18問目
https://mevius.5ch.net/test/read.cgi/db/1515071542/ よくある質問1
(問)
ID | DATE | DATA
--+----------+-----
1 | 2007-11-11 | aaa
2 | 2007-11-11 | bbb
1 | 2007-11-10 | ccc
3 | 2007-11-12 | ddd
3 | 2007-11-11 | eee
4 | 2007-11-10 | fff
1 | 2007-11-12 | ggg
このようなテーブルから、下記のように
1 | 2007-11-12 | ggg
3 | 2007-11-12 | ddd
2 | 2007-11-11 | bbb
4 | 2007-11-10 | fff
各idに対して最新の1件だけ抽出するSQLの書き方を教えてください。
(答)
select A.ID,
A.DATE,
A.DATA
from TableName A
inner join
(select ID, max(DATE) as MAX_DATE
from TableName
group by ID
) B
on A.ID = B.ID
and A.DATE = B.MAX_DATE
; よくある質問2
(問)
key data
----------------
1 a
1 a
1 b
1 b
1 a
2 b
2 a
2 a
というテーブルから
key a b
--------------------
1 3 2
2 2 1
というExcelのピボットの様なデータを取得したいのですが、どういうSQLになりますか?
a,bというのは固定なので、仮にcというデータがあっても無視して構いません。
(答)
select key,
SUM(CASE data WHEN 'a' THEN 1 END) AS a,
SUM(CASE data WHEN 'b' THEN 1 END) AS b
FROM table
GROUP BY key
ORDER BY key
; よくある質問3
(問)
ID HOGE
01 A
01 B
01 C
02 A
03 B
HOGEをAもBもCも持っている、ID:01だけ取り出すにはどうすればよかですか
(答1)
select id
FROM TableName
WHERE hoge in ('A','B','C')
GROUP BY id
HAVING count(DISTINCT hoge) = 3
;
(答2)
select *
from TableName T1
where not exists (select *
from (values 'A', 'B', 'C') T2 (HOGE)
where not exists (select *
from TableName T3
where T1.ID = T3.ID
and T2.HOGE = T3.HOGE
)
)
;
※valuesの部分(Table Value Constructor)はDBMSによって文法がかなり違うので注意 よくある質問4
(問)
列の数が可変な問合せはどう書きますか?
(答)
標準SQLでは書けません。
pivotという機能を搭載したDBMSなら一見書けそうですが実はやっぱり書けません。
Oracle 11g以降でpivot xmlというキーワードを使用すれば一応可変っぽくはなります。
が、素直にプロシージャを書くかアプリケーションで処理したほうが良いでしょう。
SQL Serverのpivot(2005以降)
http://msdn.microsoft.com/ja-jp/library/ms177410.aspx
Oracleのpivot(11g以降)
http://download.oracle.com/docs/cd/E16338_01/server.112/b56299/statements_10002.htm#CHDCEJJE
http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html よくある質問5
(問)
年月(YYYYMM)を指定し、その年月に対応する年月日を取得したい
例:201006を指定したら、以下の結果を得たい
20100601
20100602
・
・
・
20100630
(答)
SQLでは存在しないデータを生成することはできません。
この問いの場合は素直にカレンダーテーブルを用意しましょう。
どうしてもやりたければ以下のような方法もなくはないですが、
再帰問合せの本来の使い方ではありません。
やめておくことを強くお奨めします。
(PostgreSQLの連番を生成する関数なら辛うじてセーフかもしれませんが
賛否の分かれるところでしょう。)
with TEMP (NUM) as (
select 1 from dual
union all
select NUM + 1 from TEMP where NUM < 31
)
select to_char(to_date('201006', 'YYYYMM') + NUM - 1, 'YYYYMMDD')
from TEMP
where to_date('201006', 'YYYYMM') + NUM - 1 < add_months(to_date('201006', 'YYYYMM'), 1)
;
※上記はOracleの場合です。(11gR2以降)
※再帰問合せをサポートするDBMSならこれを適当に改変すれば動きますが
どのみちお奨めしません。 空文字列を入れたがるやつにかぎって、レコードによっては空文字列だったり、NULLだったりと両方想定してないといけない設計にして、運用ではまる。 SQLじゃなくてテーブル設計の質問なんですが、お願いします。
商品を複数の倉庫に保管するモデリングなんですが、現状は、
----------------------------------------------------------------
pkey | 商品ID | 商品名 | 倉庫1 | 倉庫2 | 倉庫3 | 倉庫4 | 倉庫5 |
----------------------------------------------------------------
という風になって、保管する場所が増えるたびに、倉庫カラムが増える設計になっています。
これは、
-------------------------
pkey | 商品ID | 倉庫番号 |
-------------------------
| | 倉庫1 |
-------------------------
| | 倉庫2 |
-------------------------
| | 倉庫3 |
-------------------------
| | 倉庫4 |
-------------------------
| | 倉庫5 |
-------------------------
という風にするべきなのでしょうか?
最初の設計だとカラムが増えていくのに対して、この方法だとレコードがとんでもない数になっていくのですが・・・・ >>13
@もともと1レコードに収まっていたデータを多数のレコードに分割すると、読み取りのパフォーマンスは落ちないでしょうか?
A副作用ですが、正規化することで、正規化前と比べてテーブル数が増える(20倍程度)と、結合で速度が落ちないか?
という点が不安です。 >>12
倉庫が増えたら項目増やさないといけなくなるのと
倉庫ごとに数量、単価、金額もちたくなるとさらに項目が増える
もとのデータは下のテーブル形式で、夜間処理で照会用の中間テーブルとして上のテーブルをつくればいい >>15
おっしゃる通りです。経験のなさから、そこまで考えが及びませんでした。
まずは第三正規形に正規化した状態でのパフォーマンス確認からしてみます。 >>12
その商品、特定倉庫1ヶ所にしまうのかい? SQL質疑スレでやるよりも、こちらでした方が良いかも
DB設計を語るスレ 10
https://mevius.5ch.net/test/read.cgi/db/1495438711/
答える人は同じなんだろうけどね 縦横問題はRDBができて以来定番の課題&質問になってるな
PIVOTとかも使いにくいしいい加減DBMS側でうまいことしてほしいところ 今なら
「ラクテンスーパーポイントスクリーン」
登録するだけでRポイント150pが貰える!
※Androidアプリのみ
iPhoneユーザーはWeb版から登録のみ可能
登録完了後に表示される招待コ一ドをお持ちですか?のところで
「i9WPjs」
を入力する
完了
祭りだ♪ヽ('∀')メ('∀')メ('∀')ノワッショイ >>14
あなたは30年前からタイムマシンに乗ってやってきたのですか? >>23
過去には行けるが未来には行けない。これが現代の常識。 >>25
逆にだった。時間の流れが遅いところにいると、時間の流れが速いところに戻ったときに未来にたどりつく。 現在から過去に行けるなら、未来人が現在に来ることは可能だな
現代の常識だとそうなる 点数テーブル
名前 日付 点数
A 7/27 50
A 7/28 70
B 7/27 80
B 7/28 90
ゲタテーブル
A 7/27 10
A 7/28 -5
B 7/27 -20
B 7/28 5
というような2つのテーブルがあって
点数をプラスマイナスした結果を出力したいのですが、どういうやり方がありますか?
今UNION ALLして、名前と日付をGROYP BYして
点数をSUMで集計しているのですが、これで問題ないでしょうか?
本当は例よりもjoinjoinしていて複雑なので、文も大分長くなってますしこれでいいのか不安になってます ありがとうございます!
+で繋げたら普通に足し算できたんですね・・・お恥ずかしい
ゲタのほうに該当がなかった場合点数+NULLみたいにならないか不安ですが試してみます! COALESCEなりCASEなりでNULLを0にすればいいんでない? 37の意図する事が今一分からないだが、
単純に点数テーブルとゲタテーブルをマージして
Group by して sum取っちゃ拙いのか?
MySQLだとこんな具合で
select `名前`,`日付`,sum(`点数`) from (
select `名前`,`日付`,`点数` from `点数テーブル`
union
select `名前`,`日付`,`点数` from `ゲタテーブル`
) g
group by `名前`,`日付`; >>37がやってるってのがそれだろ。
しかも>>37は正しくunion all使ってるのにお前は間違えてるし。 まあunionでもいいと思うが万が一ゲタ側のレコードに対応するレコードが点数テーブルにない時もレコード出力されちゃうから俺ならleft joinでやると思う >>37です。皆さんありがとうございます。参考になります
その後、LEFT JOINで書いたのですが、
点T
A 7/30 70
B 7/30 80
ゲタT
A 7/30 +10
A 7/30 -5
B 7/30 -10
というように、ゲタの対応するレコードが1件だけではなかったらしく
普通にLEFT JOINすると
A 7/30 80
A 7/30 65
B 7/30 70
のように複数行になってしまいました
サブクエリでSUMするしかないかなと考えているのですが
以下の2つのやり方でどちらが良いでしょうか?
後者のほうがシンプルで良いかなと思ってます
もしくは、もっと他に良い方法があるでしょうか?
@
SELECT 人, 日, 点+ゲタ計
FROM 点T
LEFT JOIN (
SELECT 人, 日, SUM(ゲタ)
FROM ゲタT
GROUP BY 人, 日
)
ON 点T.人 = ゲタT.人
AND 点T.日 = ゲタT.日
A
SELECT 人, 日, 点+ゲタの合計
FROM (
SELECT 人, 日, 点, SUM(ゲタ)
FROM 点T
LEFT JOIN ゲタT
ON 点T.人 = ゲタT.人
AND 点T.日 = ゲタT.日
GROUP BY 人, 日, 点
)
見づらく恐縮なのですが、よろしくお願いします 2番目のgroup by はやばい.
正誤で言えば、1番目が正しい ありがとうございます!
確かにAはおかしかったですね・・・
@のほうで書いてみたいと思います
ありがとうございました! サブクエリする必要はないけど
Aも別に間違いじゃないけどな
SELECT 人, 日, 点+SUM(ゲタ)
FROM 点T
LEFT JOIN ゲタT
ON 点T.人 = ゲタT.人
AND 点T.日 = ゲタT.日
GROUP BY 人, 日, 点 >>47
なにがやばくてどう間違ってるのか詳しく
どう書いてもまあいいんだが、気になるなら実際のテーブル(インデックス)構成と件数で実行計画取ってみれ date player score weekAve
2019-09-01 A 80 ?
2019-09-01 B 67 ?
2019-09-01 C 91 ?
2019-08-31 A 78 ?
2019-08-31 B 65 ?
2019-08-31 C 93 ?
2019-08-30 A 81 ?
2019-08-30 B 69 ?
2019-08-30 C 90 ?
…
というようなデータで、各プレイヤーのその日付段階での
直前1週間の平均scoreをweekAveのところに入れる方法をお願いします。 sqliteで作ったので適当になおしてくれ
select tb1.col1,tb1.col2,max(tb1.col3),avg(tb2.col3)
from tb1
left outer join tb1 as tb2
on tb2.col2=tb1.col2
and date(tb2.col1)>=date(tb1.col1, '-7 days')
and date(tb2.col1)<=date(tb1.col1)
group by tb1.col1,tb1.col2
; >>53
大変ありがとうございました。
使わせていただきます。 name, datetime, comment のテーブルでnameとdatetime で主キーとしています。
nameが重複しているものだけをリストアップするにはどうすればよいでしょうか。
A 2019/9/20 0:0 AAA1
B 2019/9/20 0:5 BBB1
C 2019/9/20 0:5 CCC1
A 2019/9/20 1:0 AAA2
C 2019/9/20 1:5 CCC2
A 2019/9/20 2:0 AAA3
の場合以下を期待します。
A 2019/9/20 0:0 AAA1
A 2019/9/20 1:0 AAA2
A 2019/9/20 2:0 AAA3
C 2019/9/20 0:5 CCC1
C 2019/9/20 1:5 CCC2
以下のSQL文で実現できますが、もっとスマートな方法はないでしょうか?
select * from xxx
where name in
(
select name from
(select name, count(*) as cnt from xxx group by name)
where cnt > 1
)
order by name, datetime HAVING使うぐらいか?
SELECT * FROM xxx WHERE name IN
(
SELECT name FROM xxx GROUP BY name HAVING 1<COUNT(*)
)
ORDER BY name, datetime >>56
出来ました!
group by はhaving でしたね。
ありがとうございました。 こんなんでいいだろ
select *
from xxx T1
where exists (
select *
from xxx T2
where T1.name = T2.name
and T1.datetime <> T2.datetime
) テーブルのレコード数が多くてnameのカーディナリティも十分高いなら
一般には>>56より>>58の方が良いだろ。 DBMSとデータ量で実測してみないとわからんな。
NoSQL系なら58の方が速そう
RDBなら56を改変して
SELECT L.*
FROM xxx L
JOIN (SELECT name FROM xxx GROUP BY name HAVING 1<COUNT(*)) R
ORDER BY L,name, L,datetime
の方が速いかも 日時が同じデータはありえないという条件をいわれてないなら
普通はこんなsqlはかけないわw > nameとdatetime で主キーとしています。 >>61
環境によるから実際に実行計画をみてみなきゃ確実なことは言えないのはその通りだけど、
そのsqlはサブクエリでfull scan 1回、外側で1回、nameのカーディナリティが高ければ
中間データも大きくなり、しかもJOINにインデックスが使われないときているから、
メモリに入りきらないようなテーブルの場合は極端に遅くなりそう。 nameのカーディナリティが高い場合、>>56や>>61では中間データが大きくなり
メモリに乗り切らないことが考えられ、>>58のほうが速い可能性がある。
nameのカーディナリティが低い場合、>>58ではexistsの条件に早くひっかかる
可能性が大きくなり、やはり>>58のほうが速い可能性がある。 >>58は相関サブクエリにインデックスが使われ、datetimeの比較は2エントリ目で
必ず判断がつくから、実のところ速度はカーディナリティにあまり影響されない。 PostgreSQL 9.6.11 にて1000000行のデータでEXPLAIN ANALYZEを付けて実行してみた。データは https://ideone.com/WTthGi のようにして作成。
各8回実行し、最初の4回は捨てた。
>>55 PostgreSQLでは副問合せに名前を付けないとエラーになるため AS a を追加
Execution time: 1202.286 ms / 1173.974 ms / 1194.647 ms / 1221.041 ms
>>56
Execution time: 1164.661 ms / 1171.337 ms / 1210.060 ms / 1179.993 ms
>>58 order by name, datetimeを追加
Execution time: 2350.302 ms / 2320.161 ms / 2345.047 ms / 2368.932 ms
>>61 R の後にON L.name=R.nameを追加、ORDER BYの,を.に変更
Execution time: 1248.337 ms / 1215.495 ms / 1222.694 ms / 1222.818 ms
↑はDBや環境、実際のデータ、インデックスの追加で変わると思う。 >>67
素晴らしい。結局最初のであまり問題ないね
最近はよっぽど遅い場合を除いて
意図が分かるように書くのがいい感じよね すいません
教えてください…
カラムは2つです(アクセスログです)
IP
CGI
複数種類あるCGIに対してどのCGIに
このIPからは何回、このIPからは何回アクセスされたというのを集計したいのですが
SQLが思いつきません…
だれか教えてください… >>69
一旦各CGIがLogに出力して
日替わりや週替わり月替わりで集計したらどうか >>69 select CGI,IP,count(*) from テーブル group by CGI,IP; Windowsでデータベースを使いたく、今xamppをインストールして、PHPから学んでる最中なのですが、
mySQL(実際はMariaDB)で作ろうと考えていたのですが、私の目的のデータベースが作れるのか、調べてもなかなか出てこなくて、
ひょっとすると、リレーショナルデータベースでは出来ないのでは?と薄く疑問に思ってるのですが、、以下のデータベースを作ることは可能でしょうか?
例えば、プロゴルフ選手権のデーターベースを作るとします
選手の個人的な情報が入ったテーブル
(名前、生年月日、プロ登録年月日、所属チーム、性別等)
ゴルフコースの情報が入ったテーブル
(コース所在地、ホール数、ホールごとの距離、パー数、運営会社、プレイフィー、年次ごとの改修履歴等)
長年に渡るゴルフツアーの大会日程のテーブル
(カレンダー、使われたコース、個人成績、各順位の賞金額、賞金総額、スポンサー等)
このようなデータを連携させて、
ゴルフツアーのテーブルの個人成績の項目に個人データのテーブルとリレーションシップを張り、
ゴルフツアーのテーブルの開催コースの項目にコースのテーブルとリレーションシップを張り、
このデータベースを使って、例えば、
◯◯選手の年次ごとのツアー成績
◯◯選手の獲得賞金学の推移
◯◯選手のコース全長に対する成績傾向
特定のコースを得意とする選手
チームとして得意なコースか苦手なコースか
などの分析用のデータとして取り出したりすることは出来るものでしょうか?
accessをちょっと齧った程度の感覚ではできそうな気がするのですが >>72
そういうことをするためにリレーショナルデータベースは存在します。 >>73>>74
ありがとうございます
安心して勉強続けます 得意とか苦手とか、心の内面的な部分はどうSQLにしたら良いだろうね その人の平均スコアより何%以上良ければそのコースは得意とか、そんなんじゃね? 数字のことはよく知らないけど、そういうのは平均値より偏差値が良いんじゃないの? 宿泊人数を日毎に集計したい。
テーブル構成は、
ID(主キー)、チェックイン日、チェックアウト日、人数
(id, startdate, enddate, guests)
以下のデータがあるとき、
1, 2019/10/1, 2019/10/7, 4
2. 2019/10/2, 2019/10/3, 1
3, 2019/10/10, 2019/10/20, 2
2019/10/1:4人
2019/10/2:5人
2019/10/3:4人
2019/10/7:0人
2019/10/10:2人
2019/10/20:0人
このように、変化がある時点のみを抽出したいのですが、
どのようなSQLが考えられますか? >>80
SQL-Server
select dates.date1 as date1, sum(coalesce(table1.guests, 0)) as guests
from table1
right join (
select startdate as date1 from table1
union
select enddate as date1 from table1
) dates on table1.startdate <= dates.date1 and dates.date1 < table1.enddate
group by dates.date1
order by dates.date1 以下のURLのSQL練習サイトで勉強しているのですが
調べてもわからなかった問題があるので押してください。
■意味がわからなかった問題
https://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial/ja
の7番目、各大陸で最大
■問題の正解を出すSQL文
SELECT continent, name, area FROM world x
WHERE area >= ALL
(SELECT area FROM world y
WHERE y.continent=x.continent
AND area>0)
■教えていただきたい点
@SQLの解釈順序
どのように上のSQLが解釈されているのか順を教えてください。
こういう風に教えてくださいますと助かります。※以下の実行順は、私が考えたのですが、何かがおかしい感じがします・・・
@()内のSQLを先に実行
Aworld yテーブルの1行目のcontinentの値を見る。
Bworld xテーブルの1行目のcontinentの値と見比べる。.continentの値が一致していたら、world yのarea の値を抽出する
Cworld xテーブルのarea の値が、world yのareaより大きければ、world xのcontinent, name, areaを抽出する。
Dworld yテーブルの2行目を見る・・・(以下行数を進めて繰り返し)
AほかのSQL文
上の自己相関サブクエリと、以下のSQLで何か違いがあれば教えてください。
(例えば、以下のSQLの場合、件数が数万件に及ぶと実行速度が極端に遅くなる等)
select continent,name,area from world where area in (select max(area) from world group by continent)
よろしくお願いいたします。
>>83
解釈としてはxとyの突き合わせだが
DBMSによってどう最適化するかは異なるから
実際は実行計画を見てみるしかない。
そのサイトの裏側が何だかわからないので手元で実行計画を見てみるといい
https://www.atmarkit.co.jp/ait/articles/0408/25/news101.html >>83
簡潔に指摘するとALL句の意味を取り違えています。
ALL句の副問い合わせは同じ大陸内の国ごとの面積を返します。
area >= ALL は (area >= 面積1 AND area >= 面積2 AND area >= 面積3) のようなものです。つまりこの場合は一番大きい面積とarea列値を比べることになります。
あなたが考えた処理方法では、@はともかくA〜Dを行っていまうと、最大の国だけでなく、同じ大陸の他のレコードまで取得してしまいます。 table1 親品番,子品番
table2 品番,品名
取り出したい内容
親品番,親品名,子品番,子品名
table1,2のjoinでON句に親品番=品番や子品番=品番とすると片方ずつは取得できますが、両方同時に取得することはできますか? table1ひとつにtabl2をふたつJOINしてやればいいんだよ >>87
ありがとうございます
週明けに試してみます SQL Server 2014です。
文字列検索で、半角濁音および半角半濁音を含むかどうか調べたいです。
ただ普通に LIKE '%゙%' と検索すると全件ヒットしてしまいます。
照合順序で区別をしてもダメでした。
どうすればいいのでしょうか?(´・ω・`) >>90
おそらく半角の濁点、半濁点が無視さらているのでしょう。
まずは自分が見ている濁点、半濁点の文字コードを調べてください。 照合順序なにでやってだめだったんだよ
バイナリ系のやつならいける気がするけど キャラクタセットも自分で調べないようでは話にならない。 条件が半角カタカナ文字だったらどうなるのか書いてくれよ。
エスパーじゃないからわかんねえよ! many to manyって中間テーブルつかわなあらわせないの? create table T (
a,
b,
unique(a, b)
)
これがaとbのmany to many >>92
ありがとうございます。
照合順序で、てっきりCS・AS・KS・WSしか頭に入ってませんでした。
BINで判別できました。 マイク製品は大文字、小文字、全角、半角文字を同じのみなすからなあ。
変な仕様だけど、SQL Serverの照合順序を変えることが、SQLの質問なのか? >>102
複合列の一意制約の構文だろうけど、どのRDBMSかは俺もわからない。 >>98は、見方によってはaとbの中間テーブルだがな ものすごく初歩的な質問すいません。
会社の業務で、OracleのデータベースからVBAを使って、データを取得しているようなのですが、この逆って出来るのでしょうか?
大量のExcelデータをVBAを使って、データベースを一気に書き換える、ようなスキルを身に付けたいと思っています。
また、このようなスキルを身に付けるにあたって、分かりやすい参考書のような書籍などありますでしょうか? 一気に書き換えるってことは
DeleteしてInsertかな?
ODBC接続してSQL発行すれば良いのでは >>109
古いExcel VBAの逆引き本に書かれている。ただ、正解はないのでどれが最適なのかは深く考えないこと。 >>110->>112
レスありがとうございます。
権限というのは、データベースに接続するためのID/PASSでしょうか?
Oracleのデータベースからデータを引っ張ってくるVBAの記述を見ると、「ID」「PASS」の
文字列があるので、これを利用できそうです。それともデータベースというのは
ID/PASSを知っているだけでは足りず、責任者の承認のようなものが一般的に必要と
なるのでしょうか?
「ODBC接続」「SQL発行」というのが、今目指していることのキーワードとなるようですね。
古い本に載っているそうですが、最新のものはありませんか?
それともネットのプログラミング講座を受講するのが早いでしょうか?
質問ばかりですいません。
よろしくお願いします。 >>113
そのID/PASSがテーブルを更新する権限があるかどうかが問題
てか、マジでそのデータベース管理してる人にそんなことして良いのか確認しなよ
ヘタこいてデータぶっ壊しましたテヘペロ
で済むならいいけど 普通DBの参照権限は貰えても更新権限は与えないよね。 そうだね
Excelで扱うデータを引っ張るような業務レベルだと
テーブル更新権限までは持たせないと思う >>114->>116
そうですか…
せっかくスキルを身に着けたとしても、更新権限が付与されないのであれば意味がないですね。
おそらく管理者に確認しても、余計な事するな、となりそうなので
ただSQLの知識はあっても損はないので、買った本くらいは通読してみようかと思います。 ぶっちゃけ、そのヤろうとしてることはクラッキングだからな
管理者の許可を得ず、データにアクセスして改竄 家のPCでSQLSERVERとかPostgreSQLとか構築してみたら勉強になる
めっちゃ簡単だし >>119
そんなことをしなくても、Excelシートをリレーショナルデータベースとして扱える。 unique cnstraintに引っかかるとエラーが帰ってくるの? このエラーをtry exceptで例外処理して重複するのを防ぎたいんだけど
commitしないとエラーがでなくて
毎回addする毎にcommitするしかないですか? >>127
普通はコミットするまでにエラーがでると思うが
使ってる言語かDBMSのスレで聞け 売上を記録するテーブルの設計について教えて下さい。
例えば商品マスタが以下の構造だとします。
----------------------------
| 商品コード | 商品名 | 単価 |
----------------------------
販売履歴を記録するテーブルは、
-----------------------------------
@| 商品コード | 商品名 | 単価 | 数量 |
-----------------------------------
と、
--------------------------
A| 商品コード | 単価 | 数量 | ※商品名は、商品コードをキーにしてマスタから取得
--------------------------
と
-----------------------
B| 商品名 | 単価 | 数量 | ※商品コードは、商品名をキーにしてマスタから取得
-----------------------
の3つのどれがいいのでしょうか?
Aの場合、販売後に商品コードが変わると、販売時の商品名が分からなくなり、
Bの場合、販売後に商品名が変わると、販売時の商品コードが分からなくなるので、
@が一番いいのかな、と思うのですが、本当にそれでいいのでしょうか? 普通1だし、商品名変わったら新しくID発行するだけで上書きはしないよね。 普通は、商品コードと数量だろ?
(属性は足りないと思うけど) その要件なら@で仕方ないと思うが、商品名の追跡が必要なら商品名ごとの
サブコードを発行しておくという手もあると思う。 何のために商品コードがあると思っているんだろうね。 値段の変動するものなら、その時の時価を記録してないと訳分からなくなるかも >>130
ずいぶん遅いレスだけど販売管理ならユーザーによって使い方が変わるからそういった点でも
できるだけ細かい情報を販売実績のテーブルに管理したほうがいいぞ 誰もがいつも表記の揺れのない正確な商品名を打てる世界を想定しなくはいけないのか? データに全ての情報を埋め込むのは汎用機システム世代
リレーションシップデータベース世代になるとマスターに
できるのはできるだけマスター化する
しかし全てマスター化すると古いマスターもずっと残さないといけなくなりマスターが肥大化してしまうのでデータに埋め込んでおくのもいい場合がある リレーショナルデーターベースとしても意末は通らんけど >>130の商品コードと商品名が関数従属しないんならべつに@も非正規形ではないんだがな ユーザーによっては商品マスタを使いまわすところもあれば商品ごとにマスタを登録するところもある
商品はセール(値引き)以外にも返品なども行う事もおおいから単純にマスタを見て単価や名称を紐づけすればOKなんて考えは
販売管理作ったことのあるやつならナンセンスじゃね
請求書や領収書なんかも変わった商品名称や単価だすとかありえんしね テーブル設計の話題は 「DB設計を語るスレ」 でやってください プライマリキーが無くてもいいテーブルがあるDBは設計が間違ってる。 tempテーブルのこと言ってんでしょ?
それならプライマリキーなくても別に構わないよ えっ、temporaryテーブル(一時テーブル)のことだよ SQLスレにいるのにテンポラリテーブルも知らないのかw SQLの仕様に、テンポラリテーブルってのが有るのか・・・ 一時テーブルという機能を持つDBMSはあるが、一時テーブルだとプライマリキーが要らない
理由なんてないよなぁ。 意味的なプライマリキーと
DBMSのPRIMARY KEY制約がごっちゃになって話が混乱してるな >>164
逆に一時テーブルの機能を持たないRDBMSってあるのかい? Oracleは18cまでまともに使える一時テーブルがなかったのね
いろいろと納得 最初は中間テーブルって話だったのにいつの間に温度テーブルの話にすり替わったのか >>166
それが混同されたとしても一時テーブルは関係ないわ SQLのスレなんで、DBMSの実装機能の話は無いのかと思ってたが,そう言うことか テンポラリテーブルはSQL-92で定義されてる標準だぞ
各実装が従ってるわけではないけど inner joinの前と後のテーブル入れ替えても同じ意味になりますか? >>176
同じ意味というのが
同じ結果セットが得られるかということならイエス
同じ実行プランが得られるかということなら必ずしもそうはならない あ、inner join on x.id <> y.id のように不等号とか使ったら結果セットも変わるわ 二つのテーブルの内部結合なら不等号だろうが結果セットは変わらん気がするが
もちろん列指定ちゃんとやるって前提だが べつに文句を言っている訳ではないよ
順序に期待するならそこまで考慮しようねって事 同じSQLですら結果の順序がどうなるかわからんのにinner joinの結合順で結果の順序とか言い出す奴って… >>183
そういう基本的なことからわかってないのにデタラメを言うやつは年齢関係なくいるから困るよね。 このスレでの話ならスルーしてれば何も困らないだろう
職場にいるんなら、それはお前がどうにかしろ
こんなとこで愚痴るなよ、鬱陶しい 2020みたいな西暦って
integerかstr かtimeのどれ型を使うのが一般的ですか? そうすか ありがとうございました
int ならorder by できますからね >>188
最近はDate型にして月日には1月1日入れてる 日付形式にすると日付ではない値は
セットできないのでデータ整合性が
保てる
日付形式で困るのは最大値だな
データベースによって違うから
日付数字8桁なら99999999とかに
すればいいけど 西暦はゼロ年、1年の扱いの違いもちょっと困ることがある 年だけをどのデータ型にするのがいいのかは
利用方法、DBMSの種類、件数、(もしあれば)規約などによる
一般的にはint, smallint, dateが候補だけど
MySQLのようにyear型があればそれも選択肢になるし
Oracleならdateは7バイトも使うのであまり選ばれない
個人的には年だけ表現したいのに関数使わずに見ると
2020/01/01って入ってるのは嫌なのでsmallintが第一候補
過去の西暦とか入力できる範囲も違うから必要ならチェック制約使う 1月2日とかが入るのを完全に排除できるならいいけど、それやるのにトリガとか使うくらいならintでいいよね。 >>198
数バイトが積み重なってレコード長が大きくなればパフォーマンスが徐々に悪化するからね 日付形式は検索するとき数字形式より遅くなる場合が多い
日付形式を検索するとき関数を使う場合が多く関数ある分遅くなる
例えばこんな感じ
Where TO_CHAR(sale_date, 'YYYY-MM-DD') = '1970-01-01'
俺は月次単位でデータを作る事が多く検索で多く使うから
年月は数字6桁でインデックス貼ってるな
年月は他のテーブルと連結する時も多く使われるので
後で変更する場合非常に面倒なのでよく考えたほうがいい
日付形式はデータ作成日時とか更新日時のではよく使う
パフォーマンス問題を引き起こす日付型
https://use-the-index-luke.com/ja/sql/where-clause/obfuscation/dates 日付型って内部は数値形式でしょう
比較したり順序を決めるのに文字列にする必要は無いんじゃないかな OracleにはSQL-92 DATEが無かったからそんな感じだったな。 >>201
知らなかった感じ?
SQL使うだけなら知らなくていいけど
DB設計するなら基礎の基礎だから知っておくといいよ とりあえずここはSQLのスレであってDB設計スレではない
そのことをまず知っておこう 物理メモリもストレージ容量も大きいのに少しのことを大袈裟に言うやつは引退した方がいい。
ハードウェアの進化に知識が追いついていない。 >Where TO_CHAR(sale_date, 'YYYY-MM-DD') = '1970-01-01'
こういうダメな例を書かないためには
SQL使うだけのやつもDB設計の基礎知らないといけないんじゃないか? 自分の設計能力の低さをハード性能でカバーされてることに気づかないやつも引退したほうがいいけどな >Where TO_CHAR(sale_date, 'YYYY-MM-DD') = '1970-01-01'
確にこれは初心者 ON DUPLICATE KEY UPDATEのIF文について質問させてください
ON DUPLICATE KEY UPDATE
fb_like = IF(fb_like > VALUES(fb_like), fb_like, VALUES(fb_like))
このIF分の第二と第三の引数と戻り値の意味を教えて頂けないでしょうか。
第一は比較条件なのは分かりますが・・・
DUPLICATE KEY UPDATEのリファレンスを調べてもわかりませんでした・・・ >>203
普通に考えて第2引数は条件が真の時に返す値で第3引数は偽の時に返す値でしょ
てか答え書いてあるだろ
> 取得した数字がレコードの数字より大きければ更新
https://qiita.com/yuzroz/items/f0eccf847b2ea42f885f >取得した数字がレコードの数字より大きければ更新
取得した数字って書き方が悪いような >>209
>物理メモリもストレージ容量も大きいのに少しのことを大袈裟に言うやつは引退した方がいい。
性能要求が低くてスケールする必要のない小規模・オンプレならそういう認識でいいかもねw >>213
質問の内容自体はINSERT文にあまり関係ないというか単なるIF関数じゃないかな
IF自体はExcelのワークシート関数と同じく条件が真(True)なら第2引数、偽(False)なら第3引数の値を使う
でこれが今回のINSERT文になると
fb_likeに設定する値はUPDATE対象となるデータのfb_like(A)とVALUESで設定しようとしているfb_like(B)を比較して
A>BならAの値(何も変わらない)、そうでなければBの値になる
例えば最高得点を更新するような場合をイメージするといいかも
ただそれならA≧Bがよさそうではある >>218
> ただそれならA≧Bがよさそうではある
価が変わらない時は更新しないような最適化はされるんだろうか? >>219
MySQLのUPDATEは値が同じならUPDATEは実行されない 同じ値で更新するかどうかは製品の同時実行制御方式による。
多くの製品は同じ値でも更新してログを残す。
同じ値と異なる値で区別する方が実装が複雑になる。 primary keyが被って他のカラムが違った場合そこをupdateするのってどうやります?
ついでに旧の値も保存したいです。 primary keyが被るって、唯一無二のレコードじゃないのか? 「そこ」を使用する場合一意に決められるように文を定義してください >>222
その主キー列は代理キーではないということか?
主キー列の値がレコードを区別するだけのものでない場合は、テーブルの設計が誤っている。 primary keyを指定してアップデートする
「そこ」とは、primary keyになる
旧の値を保存したいなら、
更新の履歴をとっておくようにする >>225
簡略化すると
商品というテーブルがあって
id(主キー)、名前、価格
というカラムで価格が変化するというような場合です
価格も主キーにするのがいいのですかね 元の質問の理解が難しいが複合主キーの第一キーをprimary keyと言ってるのかね >>228
なんでインサートで新しいレコードを作らないのですか? DB設計を語るスレ 10 [無断転載禁止]©2ch.net
https://mevius.5ch.net/test/read.cgi/db/1495438711/
スレ違いが最近多いけど、設計スレは死んでるのか? 設計の話がなぜかSQLの話にすり替わるのは初心者の特徴なのだろうか? リレーショナルデータベースの理論的な意味をすっ飛ばしてサロゲートキーあたりまえみたいな
教え方をするとこういうことになるといういい例。 >>230
同じidが被るのは良くないかなと思いました
あとどっちが最新の価格かもわからなくなると
>>231
>>232
すいませんでした移動します 「primary keyが被って他のカラムが違った場合そこをupdateするのってどうやります?
ついでに旧の値も保存したいです。」
こんな狂った質問はスルーでよかった。申し訳ない。 >>228
価格が変化すると言っても、商売の種類によって様々
生鮮食品を扱うとなればそれこそ日々変わるし
数年に一度価格見直しで一斉に変わるという業種もあるだろう
それによって設計も変わるし仕組みも変わる
相談したいなら、SQLの書き方を聞くスレではなく
DB設計の話題を扱うスレの方が相応しいと思うんだが どうしてもkey を変えたくないなら元情報用カラムをついかして元情報をそこに残すしかし複数の変更履歴残したいならば、変更用トランザクションデータを残して置けば変更履歴は追える 他システムが出力したデータをoracleのnumber(3,16)型のカラムに格納しています
もともとの値が浮動小数でそのまま出力して格納しているため、
96.3が96.29999999996や96.3000000000004のような値になっています
Oracleのsqlで、このカラムからnumber(3,3)の96.300の結果を得るにはどうすれば良いでしょうか?
アドバイスよろしくお願いします >>240
number(3,3)にcastすればいい number(3,3)って、全体で3桁、うち小数点以下3桁じゃなかったっけ? >>240
NUMBER(整数+小数の桁数、小数の桁数)だぞ
左側が多くはず
number(3,16)型とかおかしい ぶっちゃけ分かりにくいよね
その桁指定方法
誰が考えたのか知らんけど FortranやCの出力フォーマット指定に準じているみたい
Fortran
f12.5 12桁で出力,うち5桁が小数点以下.
e20.7 科学的表記の20桁で出力,うち7桁が小数点以下.
C
%4.2fの4は全体の桁数、2は小数点以下の桁数 文章みればなんとなくわかるよね
まあわかってないのは質問者と>>240だけどw SQLとCOBOLって、殆ど同級生みたいなものだろう >>249
どこがどう「同級生みたいな」もんなんだよ。 SQL-86とCOBOL-85って殆ど同級生みたいなものだろう
って話じゃろうな 流れトン切り、雑談的な質問で恐縮なんだが
みんなコードを学んでいく上で周囲の人が書いたコード見たりして学ぶのかな
なんとなく盗み見るようで気がひけるんだけど
名前出てるからこの人の参考になるなという人の時々見てるけど、こそこそやってて落ち着かない
モラルの点でどう思う? 親ID 親Name 子ID 子Name ←列名
p1 pn1 c1 cn1
p1 pn1 c2 cn2
現在、クエリで上記の形で取得できているのですが、これを
ID Name IsParent
p1 pn1 true
c1 cn1 false
c2 cn2 false
のような形で取得することはできますか?
DBはoracle11gR2です (
select distinct 親ID as ID, 親Name as Name, true as IsParent from テーブル
) union all(
select distinct 子ID as ID, 子Name as Name, false as IsParent from テーブル
) >>253
他人のものをよく見て、真似るのが基本中の基本。
さらに自分の中でも試行錯誤を繰り返す。
これをずっとやらないとコピペプロクラマにしかなれない。 p1 pn1 c1 cn1
p1 pn1 c2 cn2
p2 pn1 c5 cn5
p2 pn1 c6 cn6
p3 pn1 c3 cn3
p3 pn1 c4 cn4
だったらどう取りたいのかが少し気になったわ
必ず親の次に子をとるなら・・・ 親の次とか意味が分からんけど、それより
p1 pn1 c1 cn1
c1 cn1 p1 pn1
とかあったらどうするんだろね そもそも >>256 は何を言っているのかまったくわからない。
親子とはなんなんだ? >現在、クエリで上記の形で取得できているのですが
これから推測するに、元となるテーブルが一つ、二つあって
それからクエリ使って2行の例を導いたと思われる
だとすれば、元となるテーブルデータと取得したクエリを公開すれば
質問に対する適切なアドバイスを得れると思うが、本人は既に解決済と見える >>256です
たしかに前提条件も詳細な情報もなく
ほかの人から見れば分からないことだらけですね すみません
だいたい>>263の通りですが、あまり時間が取れてなくて解決していませんでした
>>260
IDが違えば基本的には名前は被らないですが、その例だと
p1 pn1 true
c1 cn1 false
c2 cn2 false
p2 pn1 true
c5 cn5 false
c6 cn6 false ...と取りたいです
>>261
循環はないようなテーブルですが、それを規制するものはないため、
クエリ側で循環の対策が必要ですね 親子とは商品で例えると、セット品のようなもので
子がいない(セット品ではない)ものは子品番がNULLになっています
複数テーブルですが、一つにまとめて簡素化したものが以下になります
https://ideone.com/VRo2S0
ほしいデータは Where 注文番号 = 101だとすると、
品番 品名 親か
P001,親1,true
C001,子1,false
C002,子2,false
C003,子3,false
P002,親2,true
今までは普通にSampleテーブルのような形で取得し、
プログラム側で処理していたのですが、SQLでデータ整形ができるなら
(作り直している)プログラム側がスッキリするなと思いまして質問しました 子が親になるケースもあるなら
unionした結果をID(と名前)でgroup byしてcase式使って集約
でもSQLで処理するとプログラム側で親子関係が見えなくなるから
1つの注文に対するデータ件数が十分少ないなら
SQLじゃなくプログラム側で処理したほうが柔軟性が高くていい気がする >>264
失礼。名前は直しわすれましたわ
そうなるとこんなかんじじゃないかね
select ID,Name,IsParent from(
select 親品番 as ソートキー1,1 as ソートキー2,親品番 as ID,親品名 as Name,true as IsParent from Sample where 注文番号 = 101
union all
select 親品番 as ソートキー1,2 as ソートキー2,子品番 as ID,子品名 as Name,false as IsParent from Sample where 注文番号 = 101
) as TB order by ソートキー1,ソートキー2,ID DBMS名とバージョン
MySQL 5.6
テーブルデータ
shops
id | name
------------
1 | shopA
2 | shopB
3 | shopC DBMS名とバージョン
MySQL 5.6
テーブルデータ
shops
id | name
------------
1 | shopA
2 | shopB
3 | shopC
rates
id | shop_id | rateA | rateB
-----------------------------
1 | 1 | 0.1 | 0.05
※ rateA, rateB は total_price に掛けるパーセンテージ。小数点切り捨て
orders
id | shop_id | type | name | price
-----------------------------------
1 | 1 | A | nameA | 100
2 | 1 | B | nameA | 200
3 | 1 | A | nameB | 50
4 | 2 | A | nameB | 300
欲しい結果
shop_name | type | total_price | x_rateA | x_rateB | exist
----------------------------------------------------------
shopA | A | 150 | 15 | 7 | 1
shopA | B | 200 | 20 | 10 | 1
shopB | A | 300 | 30 | 15 | 1
shopB | B | 0 | 0 | 0 | 0
説明
ordersを集計した結果が欲しいです。そのときordersテーブルが持っているtypeをshopごとに持たせたいです。つまりshopBはtypeBのorderを持っていませんが、集計結果にはtypeBも結果に入ってきてほしいです。
ほかに、ordersを集計しratesテーブルのレートを掛けたものをx_rateA,x_rateBとして集計してほしいです。
existはorderがあったかどうかの0,1です。
よろしくお願いします。 SQLはりつけられなかったわ
結局typeはordersにしか情報がないなら
select type from orders group by type
でtypeテーブルを作る
それをshopsと直積で結合してその状態から
ratesとordersを結合して集計すればいいんじゃないの
existsは結合したordersのshop_idがnullなら0それ以外なら1 >>267
1番目のselectでは同じ親品番が複数出てくるためDistinctを追加し、
union allの次のselectでは子品番のnullが出てくるためis not null を追加したところ
目的のデータが取得できました
ソートキーを入れる発想が思い浮かばなかったです
ありがとうございました なんか中継クラウドでチェックが入りインジェクションと見なされるみたい
ソースアップロードサイトに上げて、リンク張ればいいかも ここ最近Oracle使ってないから覚えてないけど
今回みたいなのはSQL1回でガチャガチャやるよりも
ストアドプロシジャで結果セット返すようにして
テンポラリテーブル作る
親データINSERT
子データINSERT
ソートして結果を返すってやったほうが自分はいいとおもってるけどね
269もtype欲しさに受注データをgroupbyとかほんとはやりたくないわ
ABしかないならそれ用のテンポラリテーブル作って結果を返すストアド作ったほうがいい気がする SQL Serverでは安易にできるけど
MySQLってストアドで結果セット簡単に返せたっけ?
Oracleはメッチャ大変だった記憶 >>276
おおお!ありがとうございます!!
すごい。
もし、shopCも入れる場合にはどのようにすればいいですか?typesとCROS JOINだと思うのですが、うまくできませんでした。
欲しい結果
shop_name | type | total_price | x_rateA | x_rateB | exist
----------------------------------------------------------
shopA | A | 150 | 15 | 7 | 1
shopA | B | 200 | 20 | 10 | 1
shopB | A | 300 | 30 | 15 | 1
shopB | B | 0 | 0 | 0 | 0
shopC | A | 0 | 0 | 0 | 0
shopC | B | 0 | 0 | 0 | 0 >>277
ordersに入っていないshop名をshopsから取得すればできるんじゃないか こんな応用も考えられないやつがSQL使うんだな
業務のSQLだったら恐ろしいわ >>278
https://www.db-fiddle.com/f/iFRAaUckQWb7FXKb3GRcC4/0
できました。ありがとうございます。
>>276
inner join (select distinct shop_id from orders) as shop_ids
この行は動きとしては cross join なんですね。
ordersのすべてのtypeと、ordersのすべてのshop_idをかけ合わせたベースとなる表をつくり、それ対して1:1になるshopsとratesをinner joinでくっけたあとに、そこにordresをで肉付けするようなイメージなんですね。
そしてsumなどの集計関数があるのでgroup byで集計する単位を決めているんですね。
勉強になりました。 >>280
>inner join (select distinct shop_id from orders) as shop_ids
>この行は動きとしては cross join なんですね。
その通り
join/inner joinにonなどで条件を付与しなければcross joinになる
意図を伝えるためにはcross joinと書いたほうがよかったかもね onかかないinner joinって標準SQLで許可されてる? 結合条件の指定がないってだけだから、許されると思う MySQLとOracleのマニュアル見てみたら省略可能になってるけど
ISO/IEC 9075-2:1999だと省略マークないね
結構いろんなDBMSで直積使ったけどエラーになった覚えははないな >>285
SQLSERVERでエラーになったような ネタだから付き合う必要はないよ。彼の最近のトレンドは直積。書き込みをよく見れば直積に絡む話ばかりだとわかる。 >>287
270だけどはじめてここに来たよ。
とても助かって感謝している。 感謝はいいけど
どういう風に理解してくれたかだよな
次に生かせないでまた質問するだけならもうやめたほうがいい >>290
>>270での質問の仕方だったり
>>280の自分の理解をフィードバックする姿勢だったり
この手のスレでは珍しいくらいのまともな質問者だろ
それに対してケチつけることしかできないなら
君は人間をもうやめたほうがいい ここで質問してくるやつは目的を書かないからタチが悪い。 ■EXISTSを使用して。
データベース:オラクル
・氏名テーブルの姓、名前を検索情報にして以下の国語テーブル、算数テーブル、
英語テーブルからやまだたろうの、最高点を1レコード抽出するSQLのご教授を
お願いいたします。
※「EXISTS」を使用した、SQLのご教授をお願いいたします。
※英語は最高点が70点と2レコード存在しますが、
1レコードのみを抽出したいです。
■氏名テーブル(主テーブル)
姓 名前
やまだ たろう
■国語テーブル
姓 名前 点数
やまだ たろう80
やまだ たろう90
すずき しろう90
■算数テーブル
姓 名前 点数
いのうえ いちろう20
やまだ たろう50
やまだ たろう90
■英語テーブル
姓 名前 点数
しばた じろう20
やまだ たろう70
やまだ たろう40
やまだ たろう70
▼結果(1レコードのみ出力)
姓 名前 国語の点数 算数の点数 英語の点数
やまだ たろう90 90 70
宜しくお願いいたします。 せめて、
こうやって見たけどうまく行かない、どうしたらいい?
みたいに、質疑出来るようにして欲しい なぜにEXISTS ??
このケースで普通使わんやろ not exists (自分より点数高い奴)
昔はmax()使うより良い実行計画吐くことも多かったんでよく使われた。 >昔はmax()使うより良い実行計画吐くことも多かったんでよく使われた。
今となってはバッドノウハウ感満々だな
>>295がどこからこんなお題を持ってきたかが気になるわ 今でもmaxだけで常に最適な計画が得られる保証はないわけだし、
引き出しとして持っておいて損はないと思うがな。 まあ、引き出しとして持っといて損はないんだろうけど
実行計画いじりたいならまずヒントで何とかならんか検討すべきだしな ヒントって、SQLチューニングでも期待通りにならない場合に使う最後の手段って印象だが。 そもそもチューニングだのなんだの、
SQLを歪めてまでパフォーマンス気にしなきゃいけないDBが欠陥商品なんだよなぁ
安いモノでもないのに 誰か exists と max で検証してみて
その上で議論しないと空回りするよ 昔はそういうテクも有効だった
今どきはそう言うテクを使う必要は激減してるから使わなくていい、と言うかわかりにくいから使うな
要するに今は極々稀に役に立つかもしれないバッドノウハウ not existsはもう少し改善できる余地あるかもしれないが
distinct必要になるし単純なmaxより優れたプランになる可能性は感じられない
http://sqlfiddle.com/#!4/08250/4 相関サブクエリはふつうnested loop joinになるが、index張ってないと最悪。
適切なindexを張っていれば集約関数を使う場合よりもfull scanの回数を抑えられる可能性はあるが、
ful scan自体大してかからないような小さいテーブルだと効果はない。 >>314
>相関サブクエリはふつうnested loop
いまどき信じられんが 適切なindex張ってれば集約関数もindex使うから関係ない
余程間抜けな集約関数使ってる時代遅れのDB以外ではバッドノウハウ oracleって連結したテーブルはupdateできないとかあって
existsを使わないといけないケースが多いな
それ以外はexistsは使わないほうがいい maxの代替で使うのがバッドノウハウってだけで
exists自体は別に使いたければ使えばいい >>318
existsはレコード件数ごと参照テーブルの検索が行われるため遅い
inner joinやleft joinで置き換え可能下記URL参照
http://kkoudev.github.io/blog/2013/09/14/sql/
特に not existsは、参照テーブルを前件検索しないと 存在しない事がわからないので特に遅いと思う マシンパワーで解決できる場合は良くないとされるる
EXISTSやINとかのほうが意図が分かり易いから使っちゃう >特に not existsは、参照テーブルを前件検索しないと 存在しない事がわからないので特に遅いと思う
indexがない前提かな? 今どきの賢いDBMSのオプティマイザなら、相関サブクエリとJoinとで同じ実行計画立ててるぞ
まあ、すべてでうまく置き換えてくれるわけではないが
相関サブクエリを速度対策のみのJoinに置き換えるのもそろそろバッドノウハウ行きだ >>321
それはDBMSとオプティマイザ次第だから実行プラン見たほうがいいぞ
LEFT JOIN+NULLチェックよりもNOT EXISTSのほうが効率いいケースは普通にある ちょっと古いけどSQL Serverでの比較
https://sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join
シンプルなクエリならオプティマイザが置きかえてくれるだろうけど
複雑になるにつれて変換されない可能性が高くなるからちゃんと確認したほうがいいと思うよ
maxの件とは種類が違う SSMSで実行計画の視覚化めっちゃ参考になるんだけど
Oracleで似たようなことできるツールないかなあ SSMSの実行計画表示みたことあるのか?
あれは他のDBでも欲しいよな
SQLSERVERの実行計画ってxmlで保存してあとからSSMSで表示できるはずだから
実行計画のコンバーター作れば良い感じにならんかなぁ Oracleで実行計画を見る方法はたくさんある
一番基本的なのはexplain planかSQL*Plusのautoexplain
ただこれはテキストベース
一番凝ってるのはEnterprise Managerで見る方法
これはグラフィカルに見ることが出来る
Enterprise EditionとTuning Packが必要だが りんご 3
バナナ 1
というテーブルから
りんご
りんご
りんご
バナナ
の出力を得たいです
個数分出力することはできますか? Postgresならgenerate_series使うと簡単にできる
CTE使えばどのDBでもできると思うけど
わざわざSQLでやるようなものじゃない
http://sqlfiddle.com/#!17/ed939/1 ちょっと変なSQL作りたいならDBは何かを書いたほうがいいと思うの
ちなみに俺が使ってるDBならできる UPSERTの逆みたいな処理をしたいです。
(挿入先テーブルにレコードが存在すればUPDATEし、挿入元データになければ、挿入先テーブルから削除する)
以下の挿入先マスタテーブルがあるとします。
-------------------------
| id | name | age |
-------------------------
| 1 | Aさん | 22 |
| 2 | Bさん | 20 |
| 3 | Cさん | 26 |
-------------------------
そして、以下の挿入元データで更新します。
-------------------------
| id | name | age |
-------------------------
| 2 | Aさん | 23 |
-------------------------
この時に、BさんとCさんのデータが消えてAさんのデータが上記のデータで更新されるようにしたいのですが、
どのようなクエリで出来ますでしょうか?
一回、マスタの全レコード削除して、挿入元レコード全てをINSERTし直すのも考えましたが、
データ量が多いのと、参照整合性制約を切ってINSERTしてまた制約を付け直す処理が必要になる為、
可能であればもっと簡単な方法を教えて下さい。 >>341
マスタテーブルをdropして
挿入テーブルをマスタテーブルにrenameする。 >>341
DELETEとINSERTの二発に分ける
・DBMSによってはDELETEでJOINが使える。
・使えなくてもWHEREでサブクエリを使えば同じことができる >>341
DBMSがわからないので回答できないが
俺の使ってるDBMSなら2回になるけどDELETEとUPDATEで可能 データ量が多いならなおのこと、1レコードずつ処理される方法より
サクッと入れ替えた方が簡単そうだなぁ。 >>341
DBMSは?
(てか、質問ならテンプレ使え) SQL ServerならMERGE一発で可
ソースに対象データがない場合のアクションはSQL標準のMERGEにはない機能なので
SQL標準のMERGEで対応したければ削除対象のキーを含む挿入元データを作成する
でもそんなんするくらいならテーブル入れ替えるかtruncate+select intoするほうが簡単
レプリしてればどの方法でも別途考慮は必要 >>341
削除したマスターのレコードを参照してるデータはどうなるの?
CASCADEでDELETE? 普通データ削除したい時は物理削除ではなく
削除用カラムを追加して削除フラグをたてるだけにする
データデースにはundo とかないので元に戻せないから
どうでもいいデータなら物理削除してもいいけどさ 外野で言うんだけどさ
マスターデータをこのようにさっくり消しているシステムって何か怖い 削除フラグは良し悪しあるからね
思考停止状態で削除フラグ入れてるところはDB設計がすぐ腐る >>349
そういう論理削除が普通だと思っていると常に論理削除レコードかどうかを意識するSQLを書かないといけなくなり、テーブルにレコードがたまってしまう。
だから古いレコードは別テーブルに移動させる方がよい。 印字した帳票と連動してるので発番したものを戻せないとか
ユーザアカウントを一時凍結するとか
理由があれば、まあ
特に意味はないけどお客が安心するから
とりあえず論理削除方式ってのはありがち
んで、容量逼迫するから、月次や年次処理で
一定期間更新がない論理削除データを物理削除する
みたいなのもあったなぁ バックアップって、障害時の復旧には意味があるけれど
個別データの復活で使えるの? 例えば社員マスタで退社した社員を物理削除して削除した社員番号で違う人を登録した場合に不都合が生じる
退社した人のデータが連結されてしまうとかがある >>342
その後の事(挿入テーブルはそのまま残す)を考えると
1.マスターテーブルをdrop&create(空テーブルで全件削除と同じ)
2.挿入テーブル全件をマスターテーブルにコピー
にした方がいいな。 >>358
それは設計のバグだろう。
もしかして自然に発生する障害みたいに思っているのかな。 このスレで言うのはなんだかそれ運用がおかしくないか? 1から設計できる立場なら避けるけど
改修とかで押し付けられた既存システムキメラとかに
まれによくあるよね 社員マスタは例えばの話ですが
他のマスターでも起こりうる
論理削除だと永久欠番にできデータの整合性を保てるが物理削除すると前に使われていたかもわからなくなりデータ不整合が発生するリスクがあるんだと言いたかった。 自然キーじゃなくて得体のしれない「ID」を使ってるとみた。 社員番号の再利用なんて聞いたことがないな。
俺が世間知らずなだけか? >>370
過去に一度であったことがある
社員数が急増して、想定した桁数で足りなくなったという理由らしい
まあ、SQL関係ない SQLの質問が入る
↓
「そもそもその設計おかしくね?」とツッコミが入る
↓
そのツッコミにまたツッコミが入る
↓
設計談議で盛り上がる バックアップなんて発想が出てくるのは、よほど小さいデータベースの話。 >>359
>その後の事(挿入テーブルはそのまま残す)を考えると
挿入テーブルを毎回新規作成すればよくね?
わざわざコピーする価値があるケースのほうが少ない気がするんだけど
古いマスターもdropじゃなくrenameすればアーカイブとして取っておける 質問者不在で盛り上がってるなw
>>349
普通とか書かない方がいいぞ
脳死で削除フラグつけるのはアンチパターンでもある
PK制約に明示的に名前つけてると
テーブル名リネームした時に変わらないでズレて悩むことがあるから注意な >>374
>挿入テーブルを毎回新規作成すればよくね?
そんな事を言い出したら質問の回答にならない。
質問者は処理後に挿入テーブルのデータを全てクリアするなんて
言ってないんだから。 テーブルを作るんじゃなくて、レコードを移動させろよ! >>377
挿入テーブルのデータを残したいならそうすればいいだけ
コピーの有無以外にもマスターテーブルを先にdropするやり方は
挿入時にエラーが発生した場合の対処が複雑化するから一般的に悪手 >>380
それならまず別名でテーブルを作成し次に挿入テーブルから別名テーブルへの
コピーをしてエラーがなければマスタテーブルをdropして
別名をマスターにrenameすればいい。
社員情報のマスターはそれなりの件数があると思うし
処理サイクルは毎日か知らんが(多分毎日だろう)、処理する度に
わざわざDB上に旧データのバックアップテーブルを追加していくのは
どうかと思う。
バックアップならDB外のエクスポートファイル(ファイル名にYYYYMMDD等をつけて)
の圧縮で残せばいいと思う。 結局、毎回新規作成w
そんな事を言い出したら質問の回答にならないw そろそろ模範解答とやらを出して、次の話題にしようぜ >>381
社員マスタならむしろめちゃ件数少ないだろ >>382
>結局、毎回新規作成w
何か問題でもあるのか?
>そんな事を言い出したら質問の回答にならないw
意味不明。
質問者の要求通りの回答をしてるつもりだけど。 消せるならDELETE(TRUNCATE)してカラムが全部同じならINSERTだろうが
制約があるから消せないって書いてないか? そこは制約を一旦無効化してやるだろう。
ただ、再度有効化するのにかかる時間を考えたら UPDATE & DELETE と変わらんかもしれんが。 >>381
単発処理ならいいけど定期処理ならまずやらない
バックアップが依存ジョブになるリスクや運用面への影響を全く考慮できてない >>391
バックアップは一緒に処理しないで
バックアップ専用の処理(他のテーブルと合わせて)でいいと思う。 >>384
質問者(>>341)はデータ量が多いと言ってる。
しかし質問者は未だに返信なしかよw 設計スレの話題になるが
>>341
のデータで年齢ってあるけど普通は生年月日を定義して必要に応じて年齢を計算なんじゃないかと思うけど
年齢なんて定義するか? >>394
>>341は項目としての例を挙げただけだと思う。
項目なんて何でもよかったんだよ。
キー項目があってキー項目でupdateしたいって事を
言いたかっただけだと思う。 単なるアンケートとかで普通にあるでしょ
アンケートごときに生年月日なんて言う個人情報を登録したくない人は多いだろうし よく見るとマスタに年齢もつのおかしいな
来年になったら更新が必要じゃん
生年月日もったほうがいいよな 飽きたなら新しい話題振ればいいんじゃない?
「ボク、このはなしつまんなーい!」
ってガキじゃないんだから 少ないデータしか扱ったことがないやつは参考にならない。 それでは難しい質問をします
下記の複数レコードを1レコードにするSQLを教えて下さい
------------------
| mail |
------------------
| aaa@hoge.com |
| bbb@hoge.com |
| ccc@hoge.com |
-------------------
これをカンマ区切りで1レコードにする例は3件だが3件とは限らない
-------------------------------------------
| mail |
-------------------------------------------
| aaa@hoge.com,bbb@hoge.com,ccc@hoge.com |
-------------------------------------------
データベースはSqlserverです >>405
縦を横にするのは頻出の質問ではありますが標準的な方法はありません
その後の利用シーンによりますがSQL ServerならUDF書くのもありです STRING_AGGでいいんでないの?
ttps://sql55.com/query/sql-server-2017-new-functions-string-agg.php >>407
listagg()は標準(2016)に定義されている
同名の関数が定義されてなくてもgroup_concatやstring_aggのような同等の関数がある
めんどくさいからやらないけどCTEでも実現可
>>405
SQL Serverなら
1. STRING_AGG (2017)
2. COALESCE
3. FOR XML PATH
ただほとんどの場合SQLでやる必要ない >>392
それバックアップ失敗してても困らない前提だよね?
renameはtransactionalに出来ないDBMSでもエラー検知して元に戻せるけど
dropはrollbackできないDBMSだと復旧モデルによってはデータロスト >>409
いろいろやり方おしえてくれてありがとうございました
COALESCEの場合は下記の様に変数使えばできるのですね知らなかった
DECLARE @STR VARCHAR(8000);
SELECT @STR = COALESCE(@STR + ’,’,’’) +[MAIL]
FROM テーブル
SELECT @STR 3件とは限らないってことはN件なんだから8000桁って指定しちゃだめだろ
アホ SQL Serverなら(max)とか別の制限かかる実質LOBな型もあるけど
元質問がSQL Serverだったから8000なんだが
このへんDBMSによってどのくらい違うんだろうな >>416
どう問題なの?
MailがメールアドレスならANKしか入らないと思うが max指定しろってことでしょ
ケースバイケースなので8000指定が駄目って事はない >>418
> max指定しろってことでしょ
maxはオーバーヘッドあるからmaxならいいかどうかもケースバイケース >>419
同じこと言い直してドヤるのやめて〜ww 左外部結合を使う というのを文にするときはどうしたいいですか?
Aを左、Bを右、xを共通として左外部結合する
みたいな言い方を考えていたのですが、正しい日本語の文があれば教えてください。 文章にすることで何を達成したいかっていう目的を書けよ
あらゆる状況に当てはまる万能な回答や
正しい回答があるという考えで通用するのは高校生まで 外部テーブル、内部テーブル、結合条件あたりが一般的な用語
(例)
Aを外部テーブル、Bを内部テーブル、A.x = B.xを結合条件として外部結合をする場合、
左外部結合なら外部テーブルを左に置いて`A LEFT OUTER JOIN B ON A.x = B.x`と書く
右外部結合なら… >>423
左外部結合なら外部テーブルをJOIN句の左側に置いて… ググったらこんなの見つけた
自然言語からSQL文を生成!リクルートのAI A3RT「SQL Suggest API」でクエリを作る
https://ledge.ai/a3rt-sqlsuggestapi/ >>422
目的は詳細設計書です。
コードは書けるのですが、日本語文にするとわかりづらく。 >>422 - >>427
助言ありがとうございます。
考えてみます。 >>427
ER図で表現できる内容ではないと思うぞ
図にするならベン図で色分けとかだろうけど
詳細設計書なら外部結合自体を知らない読み手を想定する必要はないだろうから
文章とSQLで十分だと思う
>>421
左や右はそんな重要な情報じゃないので
>>423のようにAが外部テーブル(外部表)だってことを明記するのがいいと思う そもそも、左外部結合を使うじゃなくて
左外部結合する って書くのが普通じゃないのか >>423
外部テーブル、内部テーブルという言い方は聞いたことがない。
結合方法なのにテーブルの種類みたいになっているのはおかしい。
外部表、内部表という言葉は俗語で、Oracle Databaseでは外部表はテーブルではないがテーブルとして扱えるファイルのことを差していたりもする。 >>426
それはSQLを直訳しようとしているからダメなんだよ。
どういうデータを取得したいのかを書こうとしていない。 >>426
詳細設計なら
別に日本語文章にしなくても
SQLそのまま書けばいいんじゃね?
何の為の詳細設計か知らんけど >>431
outer table, inner tableの訳な、external tableとは別
お前が聞いたことなくても一般的に使われてるぞ
“join outer table”でoracleのリファレンスでもググってみれば 自然言語言語書き下し翻訳じゃなくて設計なんだから
「XXテーブルをxxコードで探索し存在するものについてはxxを取得する」
とかじゃないのか
建前としてそもそもSQL書く前の話なんだから >>435
> お前が聞いたことなくても一般的に使われてるぞ
聞いたことないしググっても出てこん
お前がググった結果のURL貼ってくれ >>437
site検索すればいいよ
https://www.google.com/search?q="outer+table"+site:docs.oracle.com
で見つかるのが例えばこれ↓
9.3.2 Outer Joins
In ANSI syntax, the OUTER JOIN clause specifies an outer join.
In the FROM clause, the left table appears to the left of the OUTER JOIN keywords, and the right table appears to the right of these keywords.
The left table is also called the outer table, and the right table is also called the inner table.
https://docs.oracle.com/en/database/oracle/oracle-database/18/tgsql/joins.html#GUID-2174C4BA-C852-4050-9269-353A3B40B355 >>439
inner、outerの意味がわかっているのか? くるみぽんちおおおおおおおおおおおおおおおおおおおお python3.6.8で作業しています。
ttps://datadryad.org/stash/dataset/doi:10.5061/dryad.8q0s4
この度上のデータベースを利用することになり、
sqlite3でreadmeにあるコマンドを順次実行したところ、
33行目で
sqlite3.OperationalError: near "LOAD": syntax error
と出てそこから先に進むことができません。
指すファイルは作業フォルダにあるはずなのですが、SQLは素人なこともあり、修正すべき場所がわかりません。
ご教授いただければ幸いです。 SQL Server 2014です。
以下のようなテーブルがあって
記号 状態
A 0
A 0
B 0
B 1
B 0
C 0
C 1
記号「A」のような一つも状態「1」を持たない記号を知りたいのですがどのようなSQLで実現できるでしょうか?お願いします。 ずれたテーブルを投稿してしまい失礼しました。
記号 状態
A 0
A 0
B 0
B 1
B 0
C 0
C 1
状態の最大値が0の記号を出せばいけるかなと思いついたのですが
状態は文字列となっており断念しました。。。 group by havingじゃいけなかったわ
not existsで
https://rextester.com/PTTTA8276 SQL-Serverなら文字列でもMax使えるから普通にgroup byとhavingでいけるでしょ
select 記号 from テーブル group by 記号 having max(状態) = '0' やりたい事ができました
色々アドバイスありがとうございます
同じテーブルにNOT EXISTSとか思いもよりませんでした
大変参考になります NOT EXISTSとGROUP BYどっちがパフォーマンスいいんだろ 実行計画次第だから、実際のテーブル定義と件数で実行計画比較しないと意味がない
NOT EXISTS(NOT INでも)だと自己結合するから、テーブルの走査が2回必要
HAVINGだと1回で済むので、こっちのほうが早いかもしれないし
インデックスで結合するテーブルの走査が圧倒的に早ければ結合するほうが早いかもしれない
普通のHAVINGにはインデックスきかないよね?
これをインデックス付きビューにしとけばおそらくそれが最速 >>458
SQLに詳しいやつが
なんでSELECT 1使うのか調べたほうがいいよ >>456
NOT INてインデックス有効?
NOT EXISTSの方が遥かに速かった記憶が。 ぐぐったら「SELECT 1の方が速い」「SELECT *の方が速い」「オラクルのバージョンによる」「評価されないのでどっちでもいい」ってマチマチだったので、試してみた
https://rextester.com/QWAU74067 >>460
NOT INの対象のサブクエリには当然効くでしょ インデックスの話とは関係ないが
NOT IN使っても最近はオプティマイザがよろしくやってくれるから昔ほど避ける必要ない phpmyadminをxamppで使用しています
特権タブにlocalhostがありますので、あらたにユーザーを追加しなくてもいいということでしょうか?localhost=自分ということかと思いますです >>461
Oracle Databaseの慣習だと1ではなく、Xだけど、データを取得したいのか、データの有無を調べたいかの意志表示でこう書いている。 date player score movingAvg
20200502 A 90 ?
20200502 B 80 ?
20200502 C 95 ?
20200501 A 80 ?
20200501 B 75 ?
20200501 C 90 ?
…
という感じで、複数人のプレイヤーのスコアデータがあるときに、
各プレイヤーのスコアの移動平均を求めて別カラム(?のところ)
に保存する方法を教えてください。
スコアの移動平均は、その行の日付を含まないでその行の日付から
過去10日間のスコアの平均とします。
使っているのはsqlite3(python)です。
よろしくお願いします。 くそめんどくせーから日付の部分は自分で加工しろ
select date,player,score,(select avg(score) from tbl as tbl2 where tbl2.date<tbl.date and tbl2.date>=tbl.dateの10日前) from tbl たぶんこんな感じ
日付周りは適当に直して
select
*,
(select avg(score) from scoretable
WHERE player=t.player and date < t.date and date >= (date - 10)
) AS ?
from scoretable t 歯抜けがなければwindow関数でもいけるけど
歯抜けがある場合にsqliteだとwindow関数でやるやり方わからないな
rowsじゃなくrange指定でdate関数使ったやり方分かる人いたら教えて
https://www.db-fiddle.com/f/wBESjSYhMTd9hTSWyDf9kE/0 >>467
>>468
ありがとうございます!
日付部分は、20200502→2020-05-02という形にして、
date(t.date, "-10 days")などとすればできました。
いただいたアドバイスを元に、
select * , (select avg(score) from scoreTable
WHERE player=t.player and date < t.date and date >= date(t.date, "-10 days"))
as movingAvg from scoreTable t
にて、*と計算されたmovingAvgを抜き出すことができました。
この結果をmovingAvgのカラムに保存したいのですが、
保存まで1つのsql文で書くにはどう書いたらよいでしょうか?
update scoreTable set movingAvg = (select …
のような感じで試みるもうまくいかず、、お願いします。 update scoreTable
set movingAvg = (select avg(t1.score) from scoreTable as t1 WHERE t1.player=scoreTable.player and t1.date < scoreTable.date and t1.date >= date(scoreTable.date, "-10 days")) 一応俺のくせなだけだが
別名をどちらかだけつけるなら加工する側のSQLにつけたほうがいいと思う 純粋に計算で求められる値をテーブルに保存すべきかどうかはよく検討したほうがいいぞ >>471
ありがとうございます。そのままコピーしてできました!
教えていただいた皆様、大変ありがとうございました。
>>473
保存しないでメモリで計算すべきということでしょうか?
またあとでみたいので途中計算も保存しちゃってます。 全部質問で恥ずかしいのですが、もう1つお願いします。
移動平均の日付範囲の中に要素がなかったときに、
NOT NULL constraint failedというエラーとなります。
(当日を含まず、歯抜けの日もあるため)
avg()がNULLとなる場合をスキップしてそれ以外だけ
計算する方法がありましたら教えてください。 >>476
ありがとうございます。coalesceでぐぐって、
こちらのページをみて、
https://www.dbonline.jp/sqlite/function/index23.html
ひとまず、
update scoreTable set movingAvg =
ifnull((select avg(t1.score) from scoreTable as t1
WHERE t1.player=scoreTable.player and t1.date < scoreTable.date
and t1.date >= date(scoreTable.date, "-10 days")), 0.0)
としてみたらどうやらできました。
ありがとうございました。 >>469
ポスグレなら RANGE BETWEEN '10 day' PRECEDING とか書けるみたい
(https://masahikosawada.github.io/2018/07/07/Window-Frame/#fnref:syntax)
ちょっとSQL Serverでためしたけど、RANGEとか制約多すぎて使いもんにならんな
すなおに相関サブクエリでやるほうがいいパターンなんだろうかね それNULLをスキップしてるんじゃなくてNULLをゼロにしてるだけなんだが...
ちゃんとスキップしたいならWHEREに条件かけよとか
そもそもなんでNOT NULLなんだとか
いやそもそもビューで良いんじゃねえかとか
つっこみどころ満載だな プログラムに限らず、2ちゃんねるの専門系の質問スレって
どこよりもたよりになる。過去何度も助けられてる。
答えてる人々はどういうモチベーションなんだろう。
自己鍛錬的なあれだろうか。 そういえば最近自分も外れ値を除外するために移動平均をデータにセットしたな。しかしバラツキが大きいと移動平均と比較しても意味ないので標準偏差も計算してセットした。 まあ趣味的なデータっぽいからいいと思うが
自分もビューにしたほうがいいんじゃないかとは思う
日付のデータは当日分または前日分1日だけなら
毎回更新するのはコストがかかりすぎじゃないかという気もする >>477
COALESCEはSQL標準
IFNULLやISNULLはDBMS特有の関数
なので都合が悪いケースじゃなければCOALESCE使う
よく読んでなかったけど
NOT NULL constraint failedって
moving_avgがnullになる可能性もあるのにNOT NULL付けたらだめじゃないの?
10日間のスコア平均が0.0の場合と値が無いケースとの区別ができなくなる 毎日1日分のデータを登録するという運用なら
INSERTするときにさっきのAVGのデータをSELECTでひろって
INSERT〜SELECTするという手もあるけどね >>474
簡単に導出できる値を持つというのとは、二重、三重に値を持つことと同じことになる。 >>477
なんかどんどん変な慣習に引きずられているなw
他のひとも指摘しているけど、NULLを返すレコードがあるなら、そのレコードを初めから排除しとけよ。 皆様
ご指摘のとおり、自分でNOT NULLをつけており、
それがエラーになっていることがわかっていませんでした。
ビューというは知らないので調べてみます。
色々とご助言ありがとうございます。 >>477
自分のなかで決まりがなさすぎだろ。
なんとかdateという名前にしておきながら、データ型がバラバラとかあからさまに初心者。 あきらかに初心者な質問にそんな文句いってもなぁ
自分ではなにも回答してないのにマウントだけとりたいのか
なんかsqliteの解説みてると日付型ってもってなさそうだけど
データ型がバラバラってどこ見ていってるんだろうな >>487
聞くのはいいけど
自分で試行錯誤した内容でアドバイスもらうのも
ありかと思うぜ YYYYMMDDの書式が年月日だと思うのはエスパーなのかと思っただけ ID | sub
--+----
1 | my
2 | name
3 | is
4 | john.
5 | your
6 | name
7 | is
8 | jane.
こういう、あるいみ文章みたいな文字列を
スペースごとにバラバラにされてレコード化されているテーブルを
ピリオドがある行までをまとめて
group | subs
-----+--------------------
1,2,3,4 | my name is john.
5,6,7,8 | your name is jane.
という風にグループ化して取得するにはどうしたらいいでしょうか。
環境はsqlite3です。場合によっては他DBに移行も考えています... CTE使えばできそうだけど
そういうのはSQLじゃなくプログラム側で処理したほうが100倍簡単でメンテしやすいよ こんな感じかな?
SELECT group_concat(ID,','),group_concat(sub,' ') FROM (
SELECT
a.ID,
MAX(a.sub) AS sub,
SUM(CASE WHEN b.sub LIKE '%.' THEN 1 ELSE 0 END) AS cnt
FROM test_table AS a
LEFT JOIN test_table AS b ON b.ID<a.ID
GROUP BY a.ID
ORDER BY a.ID
)
GROUP BY cnt; O(n)でできるところをO(n^2)以上に悪化させてもSQLで処理する意味あるのかな なんでもSQLでやろうとする人って保守とかはあまり考えてないよな
まあ俺が関係するわけじゃないからいいけど ウィンドウ関数使ってみた
ttps://ideone.com/Zk56p2 独り言だけど、標準SQLが何でも取り入れてしまうから、もはや標準になってない。プロジェクトの規約にないことは人によって書き方がバラバラで疲れる。 sqlは広く使われてるlinterとかないからねー
formatterでさえ使って人少ない oracleの(+)で外部結合お手軽すぎてこの書き方に慣れてしまった データベースSQLSERVERで教えて下さい
変数 @Aがあってnullだったらすべて対象でnull以外だったら
その値のみ更新とかwhere句でつけたいのですが
update テーブルA set カラZ = 1
where (カラムA = @A or @A is null)
とか考えたのですが他にもっとスマートな記述ありますでしょうか (カラムA = @A or @A is null)はselectではよく使うパターン
条件が1つならif (@A IS NULL)のほうがいいかもしれないけど
たくさんあるならそのパターン使えば良いと思うよ
OPTION (RECOMPILE)を付けて各パターンで念の為プランを確認しておくこと >>511
やはりorで記述するのが多いのですね。
ありがとうございました。 with句って今まであんまり使わなかったけどめちゃ便利じゃん
副問い合わせでごちゃごちゃネストするよりも可読性が高まる PostgreSQL特有なのか他DBでも一般的なのか分からないけど
column NOT LIKE '・・・・'
column NOT IN (・・・・)
column NOT BETWEEN a AND b
と演算子の前に「NOT」をつけてSQLを書いてもOKなのに
column NOT ~ value
column NOT = value
と演算子の前に「NOT」をつけて書くとエラーになるのって、どういう根拠によるものなのでしょう?
どっちも演算子なんだから前者の書き方で統一したいと思ったら出来なくて、
そもそもNOT演算子の意味を考えたら前者も「NOT column LIKE '・・・'」と書かないと
エラーになっちゃうんじゃ?とか考えだしたら何が正しい書き方なのか分からなくなっちゃった
SQLの正しい構文規則みたいな資料って、どれを見ればいいんでしょう? >>514
NOT LIKEやNOT BETWEENのNOTとunary operatorのNOTは違うもの
INやLIKEのような一部の演算子についてだけ“NOT LIKE”が一つの演算子として働くイメージ
Postgres特有の話ではない
https://www.sqlite.org/lang_expr.html あ、なるほど、>>516の説明で腑に落ちた
プログラミング言語でも「!=」が1つの演算子であり
「a△!△=△b」みたいに「!」「=」を分けて書けないのと同じ要領で、
SQLでも「NOT LIKE」なんかが1つの演算子に相当するということなんですね
BNFはちょっと理解できてないかもだけど、
「NOT」を書く場合の構文としてはLIKEみたいな述語の直前と決められてるってことなのかな
ひとつ賢くなれました、ありがとう >「NOT」を書く場合の構文としてはLIKEみたいな述語の直前と決められてるってことなのかな
unary operator(単項演算子)のNOTのほうも別途存在してる
NOT column LIKE ‘foo%’ は NOT (expression)の形で単項演算子のNOT
column NOT LIKE ‘foo%’ は (expression) NOT LIKE (expression)の形で二項演算子的なもの
column NOT = valueは (= value)がexpressionじゃないから単項演算子として成立しない
(NOT =)という二項演算子もないので(expresison) NOT = (expression)も成立しない
IS NOTならあるので成立する PL/sql(Postgres)で以下のようなテーブルの更新処理を実装したいです
fetchを入れ子するのではと思いますがいまいち実装サンプルなどが見つからずよく分かりません
例)テーブル(userID、 productID、price)があるとして
userIDごとにpriceから値引き額(別テーブルで定義)を引ききれるまで引く更新を全てのレコードに対して行いたいとしたら
userIDごとにレコードを取得?(ここでまずループ)
上で取得したuserIDごとのレコードをフェッチ(2つ目のループ)し、
該当レコードのpriceから値引き額を引けるだけ引いて更新
値引き額を、そのレコードで引いた金額を差し引いた余りに更新
のような計算イメージ
そもそもPL/SQLの書き方自体怪しいんですが上記のイメージで実装可能なのでしょうか 確かにSQLだけでも出来るっぽい。
ttps://rextester.com/KMHR77477 SQLだけはめちゃくちゃ辛いな
そもそも注文明細的なテーブルの販売価格を直接更新して値引きする時点で設計に欠陥あるよね >>521
サンプルコードまでありがとうございます
SQLでもできるんですね
アプリ側で実装できない事情があり頭抱えてたので、この線で一度レスポンスを見てみようと思います
設計自体の欠陥もご指摘の通りで、明細一つ一つを再計算する作り自体がよろしくないですね ないから自前でFUNCTIONを定義するか直値で書くか
先人の知恵に乗っかるのが楽かと思われ
https://www.shift-the-oracle.com/code_tips.html sales
月 金額
1月 1000
2月 2000
3月 1500
ってテーブルを
1月 1000
2月 3000
3月 4500 という累計にするSQL教えて下さい 月をintegerにした数字のカラムを用意する
1-1,1-2,1-3...1-12で範囲指定してsumを12テーブル
unionして一応ソート
か? >>526
select 月, sum(金額) over (order by 月) from sales;
他のやり方もあるけどwindow関数使うのが簡単
古いDBじゃなければサポートされてる window関数ってマジで便利だよな
よくわかってない頃はアプリ側でゴリゴリやってた ちょっと脱線で悪いが、
月カラムでデータに”月”入れる? >>530
用途による
キーや条件指定で使うカラムなら入れないが
表示用の文字列を入れるカラムなら入れる場合もある 「◯年◯月」を日付型に変更したいのですが、どうすればよいでしょうか? "年"と"月"を"/"にリプレイス
末尾に日を表す数値を付けて日付型にキャスト 自分もお手軽に書くなら>>533かな
「/」「-」何を使うかはDMBSのルールに従う >>536
置換しなくてもできるならその方法を書いてよ 置換せずに数字を取り出して使うってことかもしれないけど
DBによってはparseする時にフォーマット指定できるものもある
Postgreならto_date('2020年12月', 'YYYY年MM月’)で日付型の値が返される
とりあえず質問の仕方がわるい
「どうすればいいでしょうか?」という質問の仕方するやつはロクなのいない MySQLはフォーマット指定はできるが年月だけでは日付型に変換されないみたい
STR_TO_DATE('2020年12月', '%Y年%m月')
=> null
STR_TO_DATE('2020年12月1日', '%Y年%m月%d日')
=> 2020-12-01 >>539
> 置換せずに数字を取り出して使うってことかもしれないけど
はっきり
> 「◯年◯月」を日付型に変更したいのです
って書いてあるのに何を言ってるんだよw もともとSQLでやるべき処理ではないけど
置換しないとできないと思う理由が理解できないな 出来なくはないが、置換するほうが楽だろう
そうじゃないと思うならそのやり方書けよって話だろ 難癖つける系の人がいるね
こういう人がレビュアーにいるとレビューの空気悪くなって生産的な場じゃなくなるんだよなあ >>545
もう出てますやん
楽かどうかはDBMS次第 >>544
DBMS 指定してないから多くの DBMS でできそうな方法を書くのは当たり前だと思うけど?
まあテンプレ使わない>>532が悪いという指摘ならわかるけど >>549
言い訳?
おかしいと言うならちゃんと指摘したらいいんじゃね? >>538
そもそも文字列として持っているRDBは少数派だよ >>545
暗黙的な変換に違和感がないのならやめた方がいい 顔真っ赤の言い訳厨だけでお腹いっぱいなのに
別のアホ(いつもの人)が参戦ww >>553
そういう話は>>532に言えば?
>>554
暗黙的な変換ってどこから出てきたんだ?w >>555
指摘できないなら黙って涙吹いとけw
~~~~~~~~ >>556
日付型を決まった文字列で指定する製品もあれば、そうでない製品も存在する。 ちょっとマジで>>554が何を言いたいのかわからんのだが 俺は>>558も何が言いたいのかよくわからん
恥の上塗りをしてるのはわかるけどw いつもの上塗りマンはさすがにヤベェww
置換野郎はまともだな >>562
Access知ってるボク偉いでしょ
ってか?w 「日付型にキャスト」って書いてるんだからAccessでも文字列で指定できるでしょ
文字列からは日付型の値を生成できないDBMSがあるとして
どうやって特定の日付を指定するんだろうね >>566
それは値の解釈の例だって値を生成するために指定するのは数値か文字列でしょ
仮に数値でしか指定できないとしてもそれは1発ではキャストできないという制限があるだけ >>567
ただ書いている質問に答えただけだ
いつまで面倒くさいことやってんだよ >>565
皮肉のつもりだろうが、文字列も数値も内部表現とは異なるよ。 >>568
おまえ言い訳君だろw
>言い訳?
>おかしいと言うならちゃんと指摘したらいいんじゃね? >>570
勝手にグダグダ言っててだれがだれだか知らんけどさ
質問主が知恵の足りない質問して、荒れて終息させないでどっかいっちゃったんだろ
本当に迷惑だわ >>571
質問内容はともかく>>534できちんと礼も言って終わってる
以降は>>536と>>538が起因 >>572
そうなんだ、すまん質問主さん
ならどうしようもないな
ホント適当に切り上げてくれ >>565
Access知らんのはいいとして知らないなら黙ってなよ
Accessは#2020/06/27#の形式で日付を指定できるって話でキャストとかは関係ない
そもそも「文字列でも指定できる」ことと「文字列以外の方法で指定できる」ことの違いもわかってないのか? >>572
DBMSを書いてなかったけど質問内容は別におかしくないでしょ 質問: 「◯年◯月」を日付型に変更したいのですが
回答: 「置換して日付型にキャストする」
以下斜め上レスの人
「なんでわざわざ置換するのか?」
「そもそも文字列として持っているRDBは少数派だよ」
「暗黙的な変換に違和感がないのならやめた方がいい」
「日付型を決まった文字列で指定する製品もあれば、そうでない製品も存在する。」
「日付を文字列で指定する製品しか知らないんだろ?」
「Accessは#2020/06/27#の形式で日付を指定できるって話でキャストとかは関係ない」
斜め上レスの人は入力は文字列じゃないと思いこんでるのかコレ?
そうだとしてもいろいろおかしいww >>576
> 「Accessは#2020/06/27#の形式で日付を指定できるって話でキャストとかは関係ない」
これは俺だが、>>565に対するレスで質問者とは直接関係しないから含めないで欲しい >>577
おかしなレスしてることを自覚したほうがいい
文脈読めずに普段から人に迷惑かけてるタイプ >>578
自己紹介?
どこがおかしいのか指摘できないなら黙ってなよ 質問者がアクセスについて聞いているならともかく
アクセス限定の回答するって事が間違い
これはアクセスについて知ってるよという自己紹介でしかない
あるいはアクセスの宣伝をしたいのか? >>580
バカなの?
それとも日本語が理解できないの?
> これは俺だが、>>565に対するレスで質問者とは直接関係しないから含めないで欲しい >>576
それは日付型は関係なく文字列の変換にすぎない。 >>583
そういう話は>>554, 558, 562, 565に言えよw
俺は
> Access知らんのはいいとして知らないなら黙ってなよ
って書いてあるんだし >>587
わかる
勘違いの逆恨みで放火したり
煽り運転したりするやつ Excel VBAスレでよく発狂してるおじさんと同一人物っぽいね
技術的な話しても無駄だからスルー推奨 >>590
いきなり犯罪者とか言う奴の方が怖いわ
自覚なさそうだしww 煽り運転やストーカーの思考と同じだから
どっちかと言えば、黙ってろと言う人の方が怖い 日本語の理解力なさすぎだろ
知らないなら黙ってた方が恥をかかなくて済むぞ
って言わないと理解できないのか?ww SQLを素でシークルって言ってるのを初めて聞いた
新鮮だった >>596
恥ずかしいからやめたらって言われて逆上してるだけだろw 30年くらい前、シークェルみたいな言い方してた人がいたな 問題なのはいまだにストラクチャードクエリーランゲージだと説明されるところかな。 SQLiteで作成したデータベースファイルをSQLServerで読み込むことはできますか? 何がしたいのかよくわからない質問によく答えようとするね。
ExcelファイルのXML形式のデータを直接、読み込むようなことは言っていないと思う。 >>608
>ExcelファイルのXML形式のデータを直接、読み込むようなことは言っていないと思う。
別人だが>>607のURLにはそんなこと書いてないぞ
どこ見てんの?
>>606
とりあえずスレチなのでSQL ServerのスレかSQLiteのスレへどうぞ >>607
レスありがとう
形式が違うから無理っぽいですね
他アプリで作られたデータベースファイルを参照したいのですが、
ずぼらせずにDBMSそろえたほうがよさそうですね
>>609
スレチでしたか、タイ産します >>609
よくわからん人なのでスルーでお願い
>>610
中身読んだ?
何をしたいのかよくわからんけど読み込みならODBCでいけることが多いよ
厳しい性能要件があるとか設定をいじりづらいマシンとか特殊な事情があるなら別だが
まあDBMS揃えられるならそれに越したことはないけどね 例え話がわからなかったか。質問者の表現だとまるでバイナリーデータをそのまま自分の手段で読み込む方法を知りたいと解釈できる。
回答者はそんなのおかしいからこうだと当然、示す。
この流れが自作自演に見て仕方がない。 設計の概念がないアドバイスはやめた方がいい。
ちゃんとデータ移行をする手順をわからせないと途中経過がわからないものを量産して自分も他人もはまる。 >>608
> ExcelファイルのXML形式のデータを直接、読み込むようなことは言っていないと思う。
↕
>>612
> 質問者の表現だとまるでバイナリーデータをそのまま自分の手段で読み込む方法を知りたいと解釈できる。
クマーかな?
>>613
途中経過?
ODBCとかリンクサーバーとかでググってから出直してこいよ 処理を繋いで原因不明のバグで苦しむタイプだな
別のセッションでデータが更新されることを考慮していない。 間違い指摘されて書いてもない要件でイチャモンつけるクズw SQLiteの内部データをSQL Serverに直接、読み込ませるという話なのに、勝手に脳内変換して、ODBC接続で解決させるあたりは勝手すぎる。
これはデータが動かないことを前提としたもので、かつSQLの文法そのものの違い、RDBMSの違いを安易に無視したもので、保守性にも問題がある。
SQL Serverはマテリアルズドに批判的なので、ついこう言ってしまう。
そもそも自作自演の疑いがあるんだが。 SQLiteの内部データをSQL Serverに直接、読み込ませるという話なのに、勝手に脳内変換して、ODBC接続で解決させるあたりは勝手すぎる。
これはデータが動かないことを前提としたもので、かつSQLの文法そのものの違い、RDBMSの違いを安易に無視したもので、保守性にも問題がある。
SQL Serverはマテリアライズドに批判的なので、ついこう言ってしまう。
そもそも自作自演の疑いがあるんだが。 いちゃもん付けるだけ付けて何も解決してない2重投稿のゴミ。 だから手順を踏めと言っている。エスクポート、インポートを無視して、SQLiteが保証していないODBC接続を勧める方が基地階 >>611
さんくす、ODBCで読み込みとか基本的なDB操作ならできるのかな
ちょとしらべてみます
>>617
なるほどね、SQLiteが作成したファイルは独自のフォーマットだから
SQLServerでは読み込まないほうがいいってことですか、さんくす いつものことながらDB板ではID付きを相手にしたほうが負け
論理が通じる相手じゃないんだから 一般論で言うと、質問者がID付きで書き込む事は推奨だと思うぞ じゃあ、質問者以外のID付きはNGで良いんではないか なるほど、理論が通じる相手じゃないので、スルーってことで データ移行の方法を知りたいと脳内補完するほうがよっぽど自然だと思うが
直接とか、バイナリーデータをそのまま自分の手段で読み込むとか
おかしな脳内補完してんだな >>627
SQLiteで作成した「データ」をSQLServerで読み込むことはできますか?
と書かれてるならそうとも取れるけど読みたいのは「データベースファイル」だしね
まあ質問者がそこら辺をあまり区別してないことも考えられけどね
まあ既に質問者それなりに納得してるのに今更悔しがりすぎでしょw VBAおじさんがあらわれた!
どうする?
- たたかう
- スルーする
- ID付きを召喚する 既存の複数テーブルを連結して、
連結した仮想テーブルにテーブルとしての名前を付けておく方法があったようなきがするんだけど
どうやってやるんだっけ? >>630
view?
じゃなければ最低限DBMS名と名前をつけた後に何したいかを書いてね SQLServerなんですが、Pathを格納するのにふさわしいデータ型ってなんでしょう?
nvarchar(300)?ntext?nvarchar(max)? >>634
さんくす、PathはWindows10のディレクトリのことです、例えば
"C:\Program Files\Microsoft SQL Server\80\COM\sqlvdi.dll"とかです
日本語が混ざることもありますUTF8です >>635
windowsはファイル操作の文字コードは標準ではshift-jisを
使っていると思う WindowsのファイルパスとかはUTF-16LEが標準
SQL Serverのnvarcharも基本的にUTF-16用(古いUCS-2も含めて)
2019からchar/varcharでUTF-8をサポートするようになったけど
素直にUTF-16でnvarchar使うほうが堅い
長さはデフォルトの260の制限ありで使ってる前提なのかどうかによる
制限ありのまま使っててもサロゲートペアも考えるとmax以外は安心できない
ファイルパスの文字列はインデックス用と割り切って長さを制限しておいて
それとは別にバイナリでシリアライズしたものを格納しておいて
実際にPathを使う場合はそれを使うというのも一つ windows日本語環境 の標準入出力はshift -jis のままのはず
もしユニコードに変わっていたら既存バッチファイルとか
文字化けで動かなくなる
ただしwindowsの内部処理は全世界共通だからユニコードだと思う
例えばコマンドプロンプトの文字コードを調べる場合は
下記url参照
https://qiita.com/user0/items/a9116acc7bd7b70ecfb0 >>636
そんなスレがあるのれすね失礼しました
>>637
さんくすそれでいってみます
>>638
たしかに昔からSHIFT−JISだったのにいつからか新規テキストがUTF8?16?に
なってたからエンコードかわったのかなと
>>640
サンクスなるほど特殊文字を使いまくってたら簡単に限界突破するんですね
厳密にするならテクニックが必要ですか
>>641
ゆわれてみたらたしかに過去のファイルとかの文字エンコードとか
問題出てきそうなのに >>643
いや勘違いとゆうか、メモ帳で新規作成するとUTF8になってたから
Win10からはUTF8になったのかなと SQL Serverでnvarchar型を使うときは、この文字列はUnicodeですよという指定が毎回、必要になる。
UTF-8にしておけば何もかも解決すると思ってしまったんだろうが、Windows、SQL ServerにとってはUTF-8は扱いにくい。
自分自身も常にUTF-8を意識してつかわないといけない。アスキー文字はSJISでもUTF-8でも同じ文字コードだから、日本語がない場合はミスに気づきにくい。 >>641
コマンドプロンプトのデフォルトエンコーディングが日本語環境ならcp932というだけ
それは特定アプリのエンコーディング設定のデフォルト値の話で他のアプリとは関係ない
ファイル名には絵文字も扱えるがcp932環境下で実行するバッチファイルだと
そのファイル名を文字列としては正しく扱えない >>630
Oracleの場合なら
create view か
create materialized view SQL Serverで扱う言語が多国語でないなら、SJIS選択で良いかも >>645
UTF-8なんてわざわざ使うものじゃないのね
文字エンコードなんて気にもしなくなってた UnicodeでUTF-16を使わせるものだけど、どのRDBMSもこういう歴史をたどっていて、nvarcharはUnicode用と説明している。UTF-8とUnicodeとnvarcharの関係がわかっていれば、こんなところで質問しないはず。 ググって知ったかしようとしても
バレバレなのが辛いところだね〜 使用環境オラクル
Date Remain Total
7/24 100 200
7/23 0 0
7/22 10 50
7/21 10 200
と集計した後に、稼働日換算で経過日数を把握して作業残のOK NG判定をしたいです
case when Date=today() then Remain/Total else 0 as Nday
case when Date=today()-1 then Remain/Total else 0 as N-1day
...
これだとカレンダー日で経過日数把握になるので、曜日毎や連休毎にSQLを直さないといけないです。
カレンダーマスターを見つけてくれば出来ますか?
Date Weekday
7/24 1
7/23 0
7/22 6
7/21 5
無かった場合、Total = 0 を用いて稼働日判定したいです >>653
暗黙の前提を置き過ぎててやりたいことが理解できないよ
>case when Date=today()-1 then Remain/Total else 0 as N-1day
これtoday()が7/22を返す場合、Remain/Totalは10/200で0.05になるわけ?
作業残のOK/NG判定って何? どうなればOKなの?
>無かった場合、Total = 0 を用いて稼働日判定したいです
Total = 0なら稼働日ではないと断定できるということ? 説明不足で申し訳ない
結果をそのままグラフにできるツールがあってそこに結果を投げ込もうとしている
だから0.05のOKNG判定は視覚的に工場責任者が判断
0/0は非稼働の運用になっている
稼働3日まで計算し、4日目以降はRemainの明細を別で表示させる予定 1年で365カラムのデータ
10年で3650カラムのデータ totalが0になっているレコードを除いて1日前、2日前のremain/totalの値が欲しいってことかな
ttps://rextester.com/LYWT38038
v653の SELECT * FROM t653 WHERE total<>0 ってところ、UNION SELECT TRUNC(CURRENT_DATE),0,0 FROM DUAL 追加すると今日のデータが無い場合にも対応出来ると思う ありがとうございます
方向性分かったのでやってみます
こんなサイトがあったとは!こういうのに書いて質問したほうが分かりやすいので、活用します row_number()使ってtotal<>0を条件にしてインラインビュー作ればカレンダー作れないかな?
あとはそれをjoinしてcaseでそのrow_numberを条件にして持ってくる感じ
下のsqlで0が当日、1が前稼働日になるかんじ
今外なので正しく動くか検証できず無責任ですまないが
select
date,
row_number() over(order by date desc)-1 dateno
from xxx
where date<=trunc(sysdate)
and total<>0 >>663
わからんかね?
658 を一部利用させてもらい作ってみた
ttps://rextester.com/YEOZQ54266 あー、ちょっと補足
今日の日付の代わりに固定値 2020/7/27を指定している
それとd0が今日でd1が1日前、d2が2日前…という形にしている(稼働日換算で) ■やりたいこと
.1.3.6.1.2.1.10.127.1.3.9.1.324
等の末尾だけを関数使って切り取りたい
■データベース
MYSQL5.7
■求める結果
.1.3.6.1.2.1.10.127.1.3.9.1.324
をselectすると
324
になってほしい。
■補足
上の例でいうと、324から前の数字は不定です。
登場する文字は、0-9と、.のみです。それ以外の文字が出てくることはありません。
よろしくお願いします。 ググりが足りませんでした。
SELECT SUBSTRING_INDEX('.1.3.6.1.2.1.10.127.1.3.9.1.324', '.', -1);
でいけました。
スレ汚しすみませんでした。 行き詰ってしまったので皆さんの知恵をお貸しください
DBはMS SQL Server 2012です
FROMにてROW_NUMBER()とPARTITION BYを用いて直近の日付を取得し、
SELECTにてその日付を期間指定に用いて合計を集計するということを想定して作成したSQLが以下となっています
サブTの日付が同日となるデータが存在することを失念しており、行き詰りました
同日の場合は次に古い日付を取得したいのですがどのような方法があるか教えて頂きたいです
以下のSQLを活かす必要はありません
結果として期間指定した集計値を取得できればいいですが、ひとつのSQLにて完結したいです。
SELECT
マスタT.コード
,(SELECT SUM(価格)
FROM 購入T
WHERE 購入T.コード = マスタT.コード
AND 購入T.購入日 BETWEEN サブT_2.日付 AND サブT_1.日付
) AS 価格計_期間1
,(SELECT SUM(価格)
FROM 購入T
WHERE 購入T.コード = マスタT.コード
AND 購入T.購入日 BETWEEN サブT_3.日付 AND サブT_2.日付
) AS 価格計_期間2
FROM
マスタT
--日付取得1
LEFT JOIN
(SELECT ROW_NUMBER() OVER(PARTITION BY コード ORDER BY 日付 DESC) AS RowNo
,コード
,日付
FROM サブT
) AS サブT_1
ON サブT_1.コード = マスタT.コード
AND サブT_1.RowNo = 1
--日付取得2
LEFT JOIN
(SELECT ROW_NUMBER() OVER(PARTITION BY コード ORDER BY 日付 DESC) AS RowNo
,コード
,日付
FROM サブT
) AS サブT_2
ON サブT_2.コード = マスタT.コード
AND サブT_2.RowNo = 2
--日付取得3
LEFT JOIN
(SELECT ROW_NUMBER() OVER(PARTITION BY コード ORDER BY 日付 DESC) AS RowNo
,コード
,日付
FROM サブT
) AS サブT_3
ON サブT_3.コード = マスタT.コード
AND サブT_3.RowNo = 3 >>668
10~20行程度のサンプルデータとクエリをhttps://rextester.com/とかのサイトに上げて
欲しい結果セットイメージを書いてくれ
LEFT JOIN以下のところは無駄じゃないの?って感じる 日付でgroup byしてhavingでcountが1だけとればいいんじゃね
てか直近って書いてるけど、直近三日分とかそんな感じか
まずちゃんとした要件考えたほうがいいんじゃね https://rextester.com/XKXE69398
rextesterを使ってみました
初めてなのですが見れますでしょうか?
実行結果3行目が、
3 3 200 NULL 20/07/15-20/07/31 20/07/15-20/07/15
となっていると思いますが、これを
3 3 200 200 20/07/15-20/07/31 20/07/08-20/07/15
としたいです。
集計期間にデータが無い場合はNULLのままで構いません。
正確に言うと4つの日付を取得して3つの期間の集計をします >>668
集計でROW_NUMBERする下記のようにすればいいと思います
SELECT コード,
,case when RowNo = 1 then sum(価格) else 0 end as 価格計_期間1
,case when RowNo = 2 then sum(価格) else 0 end as 価格計_期間2
FROM (
SELECT コード, 日付 ,sum(価格) as 価格
,ROW_NUMBER() OVER(PARTITION BY コード ORDER BY 日付 DESC) AS RowNo
FROM サブT GROUP BY コード, 日付
) AS M
GROUP BY コード >>671
やりたいことは理解できた
ROW_NUMBER() OVER(PARTITION BY コード ORDER BY 日付 DESC) のところを
DISTINCT DENSE_RANK() OVER(PARTITION BY コード ORDER BY 日付 DESC) にすれば良いと思う
日付が同日かどうかの判定で時刻を除いた部分での比較が必要ならもうちょい追加が必要
ただ考え方としてコード、期間、価格計で一旦まとめてから
その後に縦横変換するほうがスジがいい気がする ↓こんな感じで先に求めたい集計期間の開始/終了日の表を作る
https://rextester.com/PIL77023
んでそれと購入テーブルをJOINさせて出力用の形に整形するのは最後
集計ロジックと整形ロジックを分けたほうがメンテがしやすい >>674-676
みなさんありがとうございます
今試す時間がないので取り急ぎお礼だけで失礼します
参考にさせていただきます 結合する必要がないのに結合
SELECT句にSELECT文
集合演算の概念がないとやらかす典型 【質問テンプレ】
・DBMS名とバージョン
Access 2000
・テーブルデータ(かなり単純化しています)
(日付,品)=(801,A)(801,A)(801,B)(801,C)(802,A)(802,C)(803,B)(803,C)
・欲しい結果
日付 全 A B C
801 4 2 1 1
802 2 1 1
803 2 1 1
・SQL文
クエリ1
select テーブル.日付 as 日付, テーブル.品 as 品, count(テーブル.品) as 全 from テーブル group by テーブル.日付, テーブル.品;
クエリ2
select クエリ1.日付 as 日付, 仮全.全 as 全, 仮A.A as A, 仮B.B as B, 仮C.C as C from ((
[select クエリ1.日付, sum(クエリ1.全) as 全 from クエリ1 group by クエリ1.日付]. as 仮全
left join [select クエリ1.日付, sum(クエリ1.A) as A from クエリ1 where (クエリ1.品=A) group by クエリ1.日付]. as 仮A on 仮全.日付=仮A.日付)
left join [select クエリ1.日付, sum(クエリ1.B) as B from クエリ1 where (クエリ1.品=B) group by クエリ1.日付]. as 仮B on 仮A.日付=仮B.日付)
left join [select クエリ1.日付, sum(クエリ1.全) as C from クエリ1 where (クエリ1.品=C) group by クエリ1.日付]. as 仮C on 仮B.日付=仮C.日付;
・現実の結果
日付 全 A B C
801 4 2 1 1
802 2 1
803 2
データを集計して縦横に項目が並んだテーブルの形にまとめたいのですが、
上記のようにjoinすると、前の部分で該当なしがあるとその後が結合されません。
どうしたらいいか教えてください。 SQL Serverのやつも縦横変換にはPIVOT使える
CASE式で頑張るよりかは多少マシ >>680
PIVOTって聞いたこともなかった
調べて試したらくっそ簡単にできたwww
ありがとうございました >>674-676
みなさんありがとうございました
みなさんのヒントをいただいてなんとか実装できそうです
今回WITHとDENSE_RANK初めて覚えました
ありがとうございます SQL文の中に同じ定数が何度も出てきていて、それを変更したいときに全部変えるのが面倒なのですが、
最初にたとえばa=7, b=2みたいに宣言しておいて、SQL文の中で(データ+a)*bみたいな計算をすることはできますか? >>687
多くのRDBMSで独自にSQLを拡張してるから、DBMS何か書け >>687
「how to declare variables in <データベース名>」でググる 自分なら、SQLを呼び出す処理言語側の文字列編集機能を利用すると思う >>688
access2000です
>>689
VBAの話が引っかかってきてSQLの話が見当たりません >>691
さすがに2000とか知らんけど
フォーム作ってそこにテキストボックスなりを追加して参照
標準モジュールで関数作る
パラメータクエリにする
ぐらいじゃね >>690
ホストアプリがあるならアプリ側でパラメタ使うのが良いけどな
文字列編集はインジェクションの問題があるからお勧めしかねる sqlite3で
CREATE TABLE dup (name text, size int, inum int,md5 text, primary key (name,size,md5));
とテーブル作って,ファイル名,ファイルサイズ,i-node番号,md5の値を入れてやって,
そこから重複したファイルを探すためにはどういうクエリ書くといいでしょうか.
sizeとmd5が同じでinumは異なるが重複してる条件です.
実際には2Mファイルくらいで実行予定 on macos yosemite.
find . -type f -exec md5 \{\} \; | sort -k4 | guniq -f 3 -dD
でいけけど,サラに近いマシンなので
gnuのuniq入れるのめんどうだから試しにこういう方法だとどうかなと思って. inumがユニークならsizeとmd5でgroup byしてカウントが2以上のもの
ユニークじゃないならsizeとmd5とinumでdistinctしてから上記 >>695
ありがとうございます.
select * from dup natural join (select size,md5 from dup group by size,md5 having count(*)>1) group by inum having count(inum)=1;
こんなかんじでいけました. 漠然とした変な質問になるけどクエリ1000行のスクリプトってどんなん?
そんなん扱うことあります? テーブル初期作成時のinsert文で作ったことはある たしかにそれなら1000行いくこともありますね
なんかまだよくわからないんすけど1000行くらいのSQL書けるようになってくれ言われて、ハイ?みたいな
行数の問題かーいと SQLをスクリプトで生成するようにしてて生成結果が1000行超えたことはある
2500行くらいになってた >>699
>1000行くらいのSQL書けるようになってくれ
かなりヤバイ臭いがするから
1~2年以内の転職を見越して仕事をしたほうがよさそう データをベタで書いて行数が多いSQLを指して
1000行くらいのSQL書けるようになってくれとは言わんだろう
ビジネスロジック盛り盛りの長ったらしいストアドを書いてるんじゃないの? >>703
勢いで書いてしまうかも知れないが、
半年後訳分からなくなりそう googleて個人の検索履歴をすべて保存しているらしいんですがmysqlなんかのデーベース使ってるんですかね? GoogleならBigTableとかSpannerとかだろう >>689
ありがとう。
自分が使ってるマイナーDBでも、やりかた解ったよ。 HeidiSQLで同じテーブルをコピーしたら容量のとこが毎回違うんだけど、これってアバウトな数値なんかな?
データもテーブルの型も同じはずなんだけどな >>710
たいていのDBで、テーブルのレコードが格納されている領域はある程度の空きを作るようになっている
だから実データ量が同じでもテーブルの格納に使う容量は同じとは限らん
そのHeidiSQLとやらが表示しているのが何かわからんし、それ以外の要因の可能性もまあなくはないがな データを追加する順番が全く同じでなければfill factorとかを含めて容量が変わる可能性はある
同じデータを同じソースからデータの順序を含めて同じ方法で複数回コピーしたんなら
fill factorは同じだろうからそれが原因で容量が毎回変わる可能性低いので
圧縮の失敗とか他のリソース状況に左右される要因のほうが可能性が高いかも
もしInnoDBでSHOW TABLE STATUSを使ってるんなら
Data_lengthやIndex_lengthはおおよその値みたいだから
INNODB_TABLESPACESみて実際の値で確認が必要 >>701
遅レスでほんとすみません
他答えてくれた方々も
とりあえずまだ全貌わからずなのですが転職見据えつつでいこうと思います
ありがとうございます 旧システムとかなり違う新システムを設計することになったのですが、
旧システムからのデータの移植も必要です。
テーブル設計がほぼ別物なのですが、大まかな流れとしてはどのように進めればよいのでしょうか? >>714
> 旧システムとかなり違う新システム
> 旧システムからのデータの移植も必要
地雷臭しかしない… それ自体は別に地雷臭はせんやろ
データ移行の伴う普通のシステム移行 > かなり違う新システム
> テーブル設計がほぼ別物
これのデータ移行が普通ねぇ… システム改修じゃなくて、新システム構築なんだから普通だろ
まあSQLの問題じゃないから、これ以上はどっか設計のスレいけ >>721
はいはい、システム移行したこともないド素人の貴重な意見ありがとうございますw >>722
そんな経験不足でなんで偉そうなんだよww 自分が経験したことないから地雷臭がするんですよね。
わかりますよ。
でもその地雷臭はあなたから臭ってるだけですから。 SQLと全く関係がないし
DB設計を語るスレで思いっきりやってくれ 質問者や回答者を揶揄することでしか自尊心を満たせなくなってるんやろな
いつもの人だろうけど↓こいつと思考パターンがそっくりで地雷臭どころか地雷そのものなんじゃ・・・
https://president.jp/articles/-/38175
「35年以上ドライバーをやっているから、運転技術は並じゃないんです。みんな俺をナメやがるけど、わかっていないだけなんです」
「アイツはわかっていないんですよ。俺は邪魔するやつに注意をしてやってるだけ」 なるほど経験豊富な>>717,721の考え方を説明してくれてるのか
まあキチはどこにでもいるからw 質問です。
JavaアプリからOracleDBにアクセスしています。
selectしたSQLの結果は、
DBサーバーキャッシュされ、
ResultSetのnext()でfetch数ごとにクライアントに取得してくる
といった認識なのですが、
このときIndexなどは
最初に結果キャッシュを作るまでに影響しているだけで
next()時には参照せず関係しないのでしょうか?
それともfetchする度に条件をみて結果キャッシュを作成しているのでしょうか? >>731
>next()時には参照せず関係しないのでしょうか?
SENSITIVEかどうかによるんじゃないかな
SQLじゃなくJavaの質問なので詳しくはJavaのスレで聞いてね sqlserverとかはメモリーにキャッシュしてるけどオラクルもそうじゃねえ
メモリー容量によるんじゃねえ
javaはよくわからんけどphpならそういう時は全件配列に読み込んで配列を回す
SQLサーバのメモリーを使うかアプリケーションサーバのメモリーを使うかの違いだけどださ Javaでどういうコード書いて、それがどういうSQLで発行されてるかだけど
カーソル使ってるんじゃなかったか
ORACLEのスレ行ってカーソルの動作聞くのが良いんじゃね ResultSet.TYPE_SCROLL_SENSITIVEっつうのがあるのよ
fetchするときにDBが更新されてれば更新後のデータが取得される
気になるなら通信内容を確認したり
DB側でどういうSQLが発行されてるかを覗けば良いと思う
ただAPIで公開されている以上の動作は告知なく変更される可能性があるので
確認した動作に依存するようなコードは書かないほうが良い そんなコロコロ変わるAPIでもなさそうだけどねぇ むしろDBMSによるところが大きそうなので移植のときに影響があるだろう sqlserverのsqlについて質問いいですか?
一時テーブルから、本テーブルにデータを移行するsqlを作りたいです。
両テーブルは項目は同じだけれど、必須制約が異なり、本テーブルのみに必須制約がついている項目があります。その項目にはデフォルト値が設定されています。
Insert-Select文で、nullの場合はデフォルト値を設定するような書き方ができないでしょうか?
ISNULL(項目,default)←エラーになりますが、こういう事がやりたいです。 isnullで間違ってないと思うが使い方が間違ってるんだろう defaultは値や項目名じゃなくて予約語だからな
ISNULLには指定できないだろう
あらかじめ挿入元テーブルをデフォルト値で更新しとくのが楽だと思うが
それかwhereで条件分けして2種類のinsert select文書くとか デフォルト値にしたいカラムだけ除いてinsert intoすればいいじゃん。カラムを列記するのが面倒くさいのか >>737です
やっぱり出来ないですよね…
一時テーブルにデータあった場合は、それを登録しなきゃあかんので、valueから外すとかも出来ないんですよねー
面倒だけど、ISNULL(項目,項目のデフォルト値)を手動で設定します。
ありがとうございました。 >>737
デフォルト値はNULLが指定されたときに使われるものではない >>741
デフォルト値を勘違いする人間ばかりだから仕方ないけど、一方でNULLはNULLという値でもあるんだよ。 nullは値じゃねえよ
大概の値が書けるとこで指定出来るだけ
本来指定出来ないとこでも指定できるようになってるケースも多い >>744
NULL valueと言ったりもします。日本語だとNULL値と言います。 NULLは値がないことをあらわすのですが、NULLは値がないことを示す値で、NULLというデータがデータファイルに書き込まれます。 NULLは値がないことをあらわすのですが、NULLは値がないことを示す値で、NULLというデータをあらわすデータがデータファイルに書き込まれます。 >>737
どうしてもディフォルト値を明示したくなくてかつId列みたいな列がありレコードが一意に特定できるなら
insert into テーブル (Id, 非必須制約列)
select Id, 非必須制約列 from 一時テーブル;
update テーブル
set 制約列 = isnull(一時テーブル.非必須制約列, テーブル.非必須制約列)
from 一時テーブル
left join テーブル on 一時テーブル.Id = テーブル.Id;
みたいに一旦ディフォルト値を入れて元の値がNullで無いなら更新しちゃうぐらいしか思いつかん そもそもなぜその一時テーブルを元テーブルと同じにしないのか >>751 は一体何ができたつもりになってるんだろう… >>737
MERGE文を使えば出来そうな気がしないでもない(未検証) >>752
??
>>737のやりたいことと>>751にどういう違いがあるの?
>>737のやりたいことと>>749が違うことは理解できるんだけど >>737
あ、頑張ってMERGE文を使わなくても
拘りないなら、単純に2回insertすればいいのか
必須項目ありのものと
必須項目なしのものと
後者のinsert-selectのときに
insert項目から必須項目なしの項目を除けば
勝手にdefault値が入る 今更だけど
なお、一意制約違反は考えないものとする
で、いいの? >>753
merge に対して insert は最大一回しか書けないから無理じゃね? >>754
>>737のやりたいこと理解してる?
まあ具体的にどこがおかしいと書けてない時点で… >>755
それ既に>>739に書かれてる
> それかwhereで条件分けして2種類のinsert select文書くとか >>756
>>737自体には一意制約に関する条件はないけど? >>761
insert が書けるのは WHEN NOT MATCHED [ BY TARGET ] で、これは最大一個しか書けない あー、INSERT文にはデフォルト値をリテラルで指定せず
テーブル定義から持ってきたかったってことか
INFORMATION_SCHEMAとか使って
デフォルト値を取得してそれをISNULLに渡してやればできるが
その手間をかける意味があるのかな? なんじゃこの流れ
デフォルト値書けばいいだけのところを2回インサートとかインサートしてからアップデートとかw ほんとうに関係ないことを聞くのかもしれないですけど、データベースをチューニングするとは具体的にどのようなことを指すのでしょうか?
統計情報をいじるとか、実行計画を変更することですか?
もしそうであるとするならば現状内部に搭載されているものよりもいい設計を自分達で作るということになるのでしょうか? DBMSの設定、動作環境を変える
DB設計を変更する
SQLを変更する
アプリケーションの作りを変更する
まあ、こんな感じか 分かりやすいのは
SQLの書き方を変える、インデックス構成を変える、アプリのSQL発行回数を減らす
インデックスじゃなくテーブル設計を変更したりストレージの構成を変更したりすることもある >>769
SQLの発行回数を減らすという点だけは間違い。 >>767
そのチューニングは、俗にSQLチューニングと呼ばれるもの。
DBMSの設定を変えることもチューニングと呼ばれるが、設定を変えなければいけない状況はほぼ終わっていることを意味する。 昔はハードウェアのスペックが低く、ネットワークも遅かったから、チューニングなるものが必要だった。
いまのチューニングは性能無視の設計のせいで問題になっていることへの対応ばかり。 「アプリのDB性能をチューニング」であればSQL(DML)の改善も含まれるだろうけど
>>767の書きっぷりだとDB単体のチューニングを意図してるのかな
キャッシュ設定とか同時接続数とかパフォーマンスに関わるパラメータ設定はいっぱいあるわけで
その手のパラメータ設定もDDLの一種だからSQLの範疇・・・・と強弁しようと思ったけど
設定ファイル直書きしないといじれないようなパラメータのほうが多いか
メモリやストレージ自体を増設して物理で殴るのもチューニングだし
テーブルの結合回数が少なくなるようにあえて正規化を崩して1テーブルにまとめるとか
過去データを別テーブルに切り出してテーブルを分ける&データ量を減らすのもチューニング
古いDBMSだとSQL文中で使うインデックスを指定できたりもしてそういうので性能改善するのもチューニング
少量であるマスタデータについてアプリ側でstaticに保持して都度DBから取得しないようにするのもチューニング
どこまでがDBのチューニングに該当するかは、>>767が意図してるチューニング対象次第 皆さんかなりわかりやすかったです!
ありがとうございます。
じゃあ自分も既存のSQLを効率化するために変更したことがあるのでチューニング経験があるって言えば嘘にはならないわけですね >>776
具体的に何をどうしたのかと必ず聞かれるから、結構、面倒な話になるよ。 集計の書き方がわからず、どなたか教えてください。
■DBMS名とバージョン postgreSQL 10.14
■テーブルデータ
id hiduke basho jikan ninzu
--------------------------------------------
1 2020/10/01 東京本社 09:00 3
2 2020/10/01 東京本社 10:00 6
3 2020/10/01 東京本社 11:00 9
4 2020/10/01 大阪支社 09:00 0
5 2020/10/01 大阪支社 10:00 2
6 2020/10/01 大阪支社 11:00 1
7 2020/10/02 東京本社 09:00 3
8 2020/10/02 東京本社 10:00 0
9 2020/10/02 東京本社 11:00 6
10 2020/10/02 大阪支社 09:00 0
11 2020/10/02 大阪支社 10:00 5
12 2020/10/02 大阪支社 11:00 2
■欲しい結果
東京本社
2020/10/01 2020/10/02
09:00 3 3
10:00 6 0
11:00 9 6
大阪支社
2020/10/01 2020/10/02
09:00 0 0
10:00 2 5
11:00 1 2
■説明
来店者の人数の集計で
場所と日付・時間の集計表を作成したいです。
場所の数は少ないので各社ごとに問い合わせてもよいと思います。
よろしくお願いいたします。 >>778
そもそもそれ集計ですらないだろw
表に組みたいならアプリ側でやった方がいい
支社単位ならまだ無理やりやれなくはないけど「東京支社」とか「大阪支社」とかどうやって出力する気なんだ? >>779.780
確かに集計ではないですね。
質問として適当ではなかったと反省しています。
実際は、関東地区(管轄する本社支店)の来店者数とか
全社での来店者数とかが必要になってくるわけでして。
支店ごと、地区ごとで、問い合わせるのはよいのですが、
アプリ側で加工するのではなく、
SQLの結果を回して表示できたらいいなと思っての質問です。
よろしくお願いいたします。 case式やcrosstabでできるけど
メリットないからアプリでやるべき
それと対象の日付数が固定でないなら
日付を縦に時刻を横にしたほうがいい 使ったことないけどrollupでなんとかなるんじゃね >>781
SQLの結果をどうやって表示するんだ?
何らかのアプリが必要だと思うが…
まさかpsqlで表示させるとかか? >>778
ムリにでもSQLで
表整形したいってのなら
それはそれで頭の体操っぽいお題か 返信ありがとうございます。
SQLの結果をPHPで取得してforeachで回して表示するつもりです。
>782
そうですね。時間が横軸ですね。
時間固定で、日付が変動すると、私の拙い文章でよくわかっていただけました。
びっくりです。
SQLで元データを取得して、PHPで加工組直しして表示するよりも
SQLでデータをずばりを取得して、PHPで行表示の方がシンプルでないですか。
全社、あるいは東京と大阪の合計の日付・時間のクロス(?)集計は
どのようなSQLを投げますか?
みなさんは、データを丸っと抜いてアプリで集計しますか? >SQLでデータをずばりを取得して、PHPで行表示の方がシンプルでないですか。
同意。
時間横軸固定ならシンプルにCASEでいいんでない?
SELECT
basho,hiduke
,SUM(CASE jikan WHEN '09:00' THEN ninzu ELSE 0 END)
,SUM(CASE jikan WHEN '10:00' THEN ninzu ELSE 0 END)
,SUM(CASE jikan WHEN '11:00' THEN ninzu ELSE 0 END)
FROM テーブル
GROUP BY basho,hiduke
ORDER BY basho,hiduke PHPって縦横変換が簡単にできないの?
transposeとかそういう名前の関数でだいたい一発なんだけど phpなら表示はwebページだと思うけど横長のテーブルは
横へのスクロールが面倒で見にくいから縦長にしたほうが
いい。人間の目は横方向にスライドして見ていくのが苦手だから比較は縦方向に並べたほうがいい。 SQLの場合はピボットする時も含めて
基本的に横のカラム数が固定で縦の行数が可変なんだよ
逆もできなくもないけど面倒になるだけ >>791
null渡すのがなんか微妙だけどそのくらいでできるならアプリでやったほうが簡単そうに思える 出張があって返信できませんでした。
みなさん、ありがとうございます。
>787 SQLありがとうございました。その線でいきます。助かりました。
>788 縦横といいますか、CでもJava(多分)でもPHPでも多元配列に入れて添え字の
入れ換えだと思います・・・。>791さんはarray_map使って格好いいです。
私はたぶんfor文を入れ子にするとかの泥臭いやり方です。 すみません、
SQL Server Developerエディションについて教えて下さい。
このエディションは開発用となっていますが、機能的にはスタンダードと同レベルで使えるのでしょうか?
また実稼働では使用不可とはおもいますが、ライセンス的にはどこでみわけてるのでしょうか?
使用していると定期的に確認メッセージが出たりするのでしょうか? >>794
>>1 を読め
> このスレは
> 「こういうことをやりたいんだけどSQLでどう書くの?」
> 「こういうSQLを書いたんだけどうまく動きません><」
> などの質問を受け付けるスレです。
なのでこっちへ行け
Microsoft SQL Server 総合スレ 12
https://mevius.5ch.net/test/read.cgi/db/1534679537/ 質問させてください。
Postgresql 9.6を使用していますが、他のでも似たようなことができれば参考までに教えてほしいです
テーブル名:TEAM
------------------------
team_id name nation
1 Ferrari Italy
3 Mercedes German
テーブル名:DRIVER
driver_id name car_number age team_id
-----------------------------------------------------
1 Hamilton 44 35 3
2 Bottas 77 31 3
3 Leclerc 16 23 1
4 Vettel 5 33 1
ほしい出力結果:
ID TEAM DRIVER_A CAR_Num_A DRIVER_B CAR_Num_B
-------------------------------------------------------------------------------------
1 Ferrari Leclerc 16 Vettel 5
3 Mercede Hamilton 44 Bottas 77
説明:
各チーム2人のドライバー情報がありますが、チーム毎に一つのレコードで、かつドライバー毎にカラムを分けて出力したいです。
今はそれができないので、以下のようにドライバーAとBでカラムを分けずに一つのカラム内で,区切りで表示させてます
SELECT
TEAM.team_id as ID
TEAM.name as TEAM
string_agg(driver.name, ',' ORDER BY driver_id) as DRIVER
string_agg(driver.car_number, ',' ORDER BY driver_id) as CAR_Num
FROM TEAMS
LEFT JOIN driver on TEAMS.team_id = driver.team_id
ORDER BY
TEAM.team_id 書き忘れましたが、テーブルは弄れないです。出力方法だけでどうにかしたい。
説明にある現在の出力結果は↓みたいな状態
ID TEAM DRIVER CAR_Num
------------------------------------
1 Ferrari Leclerc,Vettel 16,5
3 Mercedes Hamilton,Bottas 44,77
TABで区切ってたので表示が見づらくすみません team_id、team_id + 1 で
二人分のdriver_idを求めても良いのかな >>799
引退などでdriverテーブルからドライバーが削除される場合、driver_idにが必ずしもdriver_id+1じゃなくなる場合があります。
たとえば上記例でBottasが引退してnewbieという新人がMercedesのドライバーになった場合、newbieのdriver_idは5になるので…できないことになるかと team_idとdriver_idを紐付ける情報が無いと無理でしょう
その情報をもたせた新しいテーブルを作ると言うのは? >>801
自分はSELECTするだけで作れない立場なんです…
string_agg(driver.name, ',' ORDER BY driver_id)でHamilton,Bottasって配列みたいになっているはずなので
そこからSPLIT(string_agg(driver.name, ',' ORDER BY driver_id)',', 1)みたいにしてn番目の要素を取り出すことができればいいんですが >>802
どのチームのドライバが引退して新人が来るか分からないんでしょ?
そうするとテーブル途中のドライバが引退し、最後に新人が追加されることもあると思うよ >>803
確かにそうなのですが、ドライバーが引退した場合、そのレコードは削除(使用不可)されるので、
例えばdriver_idが3のBottasが引退して削除、その後DRIVERテーブルにdriver_idが5のnewbieがteam_id 3として新規追加された場合、
string_agg(driver.name, ',' ORDER BY driver_id)の結果はHamilton,newbieのように出力されるからいける気がしたんです Bottasのdriver_idは2でした。失礼しました 普通にsplitできて解決しました…失礼しました。
split_part(string_agg(driver.name, ',' ORDER BY driver_id),',',1) as DRIVER_A,
split_part(string_agg(driver.car_number, ',' ORDER BY driver_id),',',1) as CAR_Num_A,
split_part(string_agg(driver.name, ',' ORDER BY driver_id),',',2) as DRIVER_B,
split_part(string_agg(driver.car_number, ',' ORDER BY driver_id),',',2) as CAR_Num_B >>797
もう解決したみたいだけどwindow関数使うやり方を書いておく
https://rextester.com/FYRWPG99446
こういうのはアプリ側でやったほうが簡単だしテストや変更管理も楽でいいと思う select date(time),count(*) from a group by date(time);
これで日付毎のカウントは出せるんですけど、やりたいのは、その日付までのcountなんです。
それを出来ればワンライナーでやりたい
出来るでしょうか? 100m走の記録で、
名前、日時、記録、付随情報
というデータがたくさんあります
全記録の最高はMaxで簡単に求まりますが、歴代最高の変遷を一覧にして、そのレコードの全項目を表示させたいです
JOINを何度か使えばできないことはないのですが、ものすごく重くなってしまいました
できるだけ軽く一覧を出力するにはどうしたらいいか教えてください すみません、自己解決しました
WHERE句に、SELECTでその日時以前の記録の最高を取得してそれがレコードの記録と一致しているものというふうに指定したらあっさり出ました
お騒がせしました select T1.*
from TableName T1
where not exists (
select *
from TableName T2
where T1.日時 > T2.日時
and T1.記録 > T2.記録
)
; CREATE USERはCREATE文とUSER句によって構成されているの?
それとも、CREATE USER文? 専ブラBB2Cでワッチョイを正規表現でNGしたいんだけどうまくいかない
第2オクテット(仮にXXとして)だけ固定でこれじゃダメだろうか
.*XX.* ちょっとみなさん
SQLでCASE WHEN...って書くとSQLがわけわかんなくなるから
なるべくコードでやるようにしてたんですが
逆なのか!?
じつはSQLだけで独立してテストできるから
コード上で分岐がいらないから
SQLのほうにCASE WHEN書いたほうがいいんですか!??? まさか抽出条件までをコード実装してるのか?
ありえんだろ caseを全否定するならなら最初からちゃんと書けよ
1つの抽出項目を複数カラムで共有する程度でわかんなくなるなら
コードでやっておけば良い わからんだけで
テストはしやすい
テストしやすいんだ 開発とメンテ要員で持ってる手駒と相談しな
SQLじゃない >>824
そう感じる人はSQLで書くほうがいい選択 >>816
SQLにするとテストはいらないという不思議な日本人はかなりいるのでそうなることがある。 SQLはストラクチャードクエリーランゲージの略ではないよ。 CASEをSQL内に移動しまくったが
変更がSQL内で完結しなくなって一瞬で破綻した
結局どっちも手入れなきゃいけなくなるなら
最初から融通が利くプログラムに書いたほうがいいじゃねーか 移動しまくるほどCASE式使うのは使い方がおかしいか設計がおかしい可能性大 おかしい世界に合わせなきゃ生きていけないんだよおおおお 修正先のSQLってプログラムとべつに存在してるのか? ストアド使うパターンと埋め込み使うパターンとあるからな その状態で>>828みたいなことになるなら俺も設計がおかしいと思うぞ Excel脳だとひとつ上の行の列〇〇が△△ならこの行の列□□を■■するなんて平気で言うからw それはCASE式だけじゃ解決できないしSQLでやるべき処理でもないな ネットの掲示板みたいなデータって、以下みたいに連番で管理するのが普通だと勝手に思ってるのですが、
何千億件にもなるかもしれないレコードから数個のレスを抽出する場合、全レコード走査みたいになってパフォーマンスが落ちたりしないんでしょうか?
----------------------------------------------------
| スレッド番号 | 自身のレス番号 | 内容 |
|--------------------------------------------------|
| 12345 | 1 | 内容 |
|--------------------------------------------------|
| 〜数千万の 他スレのデータレコード〜 |
|--------------------------------------------------|
| 12345 | 2 | 内容 |
|--------------------------------------------------|
双方連結リストにして、再帰クエリで[次のレス番号]が _ になるまで辿るのと、どっちがパフォーマンスいいのでしょうか?
-----------------------------------------------------------------------
| スレッド番号 | 自身のレス番号 | 次のレス番号 | 内容 |
|---------------------------------------------------------------------|
| 12345 | 1 | 2 | 内容 |
|---------------------------------------------------------------------|
| 12345 | 2 | _ | 内容 |
|---------------------------------------------------------------------| >>837
スレッド番号+レス番号で常にデータが並ぶようにインデックス貼るから
後者が前者よりパフォーマンスがよくなることはない
レス番1の次はレス番2なのはわかりきってるのに
それをわざわざデータで管理するのは無駄
現実的なことを言えばすべての板のすべてのスレを1つのテーブルで管理しないし
キャッシュするので毎回DBのテーブルを読みに行ったりもしない 連結リストはないにしてもクラスタ化インデックスのないDBだとパフォーマンスの問題出てくる
パーティショニングで軽減できるけど件数が多いと困りそう
クラスタ化インデックスがあるDBでもインサート量によっては
ページスプリットが頻発して問題が出てくる可能性がある
てことで今ならRedis使うかな >>837 はただ単にインデックススキャンの概念がわかっていないだけじゃないのか SQL Serverで統計情報を一気に百個作れるクエリって書けますか…?
一個一個作るの大変なんです… SQL Serverで統計情報を手動で作る必要があったことはないな
必要ならクエリを生成する簡単なプログラム書けばいいんじゃないの?
条件の種類が多ければ簡単じゃないかもしれないけど 検証を行いたくて取り敢えず検証環境に統計情報を100個ほど作成する必要があるんです…
出来ればそのクエリを教えていただけるとありがたいです… 検証でいきなり100個も手動で作る意味がわからん
リンクのページに説明してあるAUTO_CREATE_STATISTICS オプションやAUTO_UPDATE_STATISTICS オプションは理解してる? MS SQL Server 2000でConcat関数を使いたいのですが
ストアドで作れますか? ISNULLと+で基本同じことはできる
が20年前のバージョンを使う意味がわからん どの製品も
ドキュメントが都合の悪いことかいてなすぎ
データベース界隈闇が深すぎる SQLがエラーになったとき
なんでエラー番号がついてないんでしょうか。
調べにくすぎます エラーメッセージはOracleが一番不親切だけどなw >>853
あえて変えてないだけだよ。他のRDBMSは原因がたくさんあっても、すべて同じだったりとこっちの方が困る。SQL Serverなんてどうすりゃいいのかわからないエラーコードをはく。 MySQL系はなんか間違ってますというエラーメッセージばかり。 Oracleが最も不親切
次にMySQLが不親切
どっちもボラクル 「ORA-XXXXX?なにこれわけわかんない。もっと親切なメッセージ表示して!」 あえてエラーメッセージを不親切にすることで
DBコンサルティングwな仕事を作ってんだよ
リテラシーの低い時代遅れの企業でしか使われないRDB業界のCOBOL マニュアル読めない顧客のかわりに仕事するのはごく普通のことだが >>859
製品マニュアルを無視するタイプでしょ? ORA-12550
詳細: 構文エラーが発生しました >>841
メンテナンスプランで統計情報の自動更新できるけど SQLって独学でスキル伸ばすの難しいですね
独学でやろうにもテストデータやテスト用テーブルを用意するのが手間
そもそも大量のテーブルJOINしたりwindow関数で優先度付けたりと複雑なSQLは業務用件をなんとか実現するうえで出来上がるものだし独学だとそういうのを書く動機や発想がないというか
独学で時間かけてダラダラやるより実戦で2週間ほど揉まれたほうが圧倒的に伸びる テストデータやテーブルを用意するのが面倒だと感じるならDBMSが用意してるSample Database使えばいい
SQL ServerのAdventureWorksやWideWorldImportersのようなやつ
データ量が足りなければインサート文を生成するスクリプトか直接インサートするスクリプトを書いてデータを足せばいい
100万件くらいならそれで十分
簡単なスクリプトを書く技術力を持ち合わせてないならSELECT INSERTとかSQLの範囲でできることをやればいい
それもまた勉強になる Oracleがややこしすぎるからそういう印象になるのかもしれない
インストール簡単なフリーの使えよ Oracleはインストールだけで400万とってた時期あったなww
そりゃ売れなくなるよ どのランキングみてもいまだにOracleがトップシェアだが、売れなくなったってのはどこの話? 大阪市のシステムでOracleにバグがあると分かってたのに何も通告しなかった
シェア以前の信義の問題だな MySQL込みでベンダーとしてはOracleがトップシェアですってオチでしょ
オラクル信奉者は世情に疎くて技術力が低いやつが多くて嫌だよねー ほらね、リテラシーが驚くほど低い
db-engines.comのランキングはpopularityであってマーケットシェアではない
販売数量や金額などの情報は全く加味されてないデータ
2番目のstatista.comは1番目のdb-engines.comが元ネタなので同じ
3番目のt4はMySQL+OracleでベンダーとしてはOracleがトップですよって書いてる 商用DBMSでOracleがトップシェアじゃないというならトップはMS SQL Serverか?
Expressを数に含めるのかどうかとか難しいな。 適当にググってもだいたいORACLEっぽいけどなぁ
まぁぺーぺーSEにはどうでもいいけど >>877
信頼できる調査会社のレポートはタダじゃないんだよ
個人で買えるような価格じゃないから必要なら会社で買ってもらってくれ オラクルのAnnual Report見れば
新規のライセンスが右肩下がりなのはすぐわかるよ
Javaの有料化はDBの落ち込みをカバーするため さっそくサイト見にいったらいまだにWeb Forms使っててビックリ
前々から思ってたがオラクルってWeb周りの技術力ないよな Web+DBが流行り始めた当時、まだcgiのサイトも多かったけどmod_plsql使ったOWSは爆速だったな。 >>884
自分の仕事が減る恐怖から批判しても意味はない。オラクル社はビジネスとしてやっているんだから、サポートに費用がかかることを勧めるはずがない。 >>888
その中途半端に古い知識で語るのはやめろよw Webサイトを見てどうとか周回遅れにもほどがある。 Web周りの技術力ってISSとWebSphereとOASのどれが優れているかとかいう議論ならわかるが、
「あそこはまだWebForm使ってるんだって。ププw」って優越感感じてるなら逆に恥ずかしい。 Google Formの利用拡大をどう非難できるのか、彼に尋ねてみたいわ。 だいたいWebLogicを擁するオラクル社に対してWeb技術が低いとか頭がおかしいのかね。 シェアじゃなくてどれだけビジネスとして成功しているかだろw なんというか>>874の言う通りだな
一人だけならいいんだけど いまだにWeb Forms使っててビックリ→Web周りの技術力ないよな
ここにどんな論点が? >>898
それは「Oracleをdisる俺に反論する奴は全員Oracle信奉者」ってやつだな Web画面屋さんの仕事が減ってカリカリしてんのかな? Oracle APEXを使っていれば、オラクル社のサポートがあるんだから何が気に入らないのかさっぱりわからない。 GoogleやアマゾンもOracle使ってるの?
それならシェアは大きいだろうなw シェアにこだわる理由がわからない。数はどの製品も右肩上がりなんだし。 無償版を含めるとOracle DatabaseとSQL Serverで現実は9割だろうな。 MySQLの性能を上げるわけには行かないんだろうな よく勘違いされるけど、MySQLはサン・マイクロシステムズを買収したら、くっついてきたもので、オラクル社が買収したわけではない。 >>892
>Web周りの技術力ってISSとWebSphereとOASのどれが優れているかとかいう議論ならわかるが
わかんねーよwww
わかるのはお前だけやぞ
ISSてw とりあえずWebと言っておけば、時代に取り残されていないと思っているんだろうな。 Oracleもクラウド事業ってやってたんだっけ?
シェアはどれくらい? だから単なる誤字をあげつらっても恥ずかしいだけだってw >>914
AWS上で動いているOracle Databaseの多さを知ったらびっくりするタイプ? >>915
単なる誤字をあげつらってると捉えるほうが恥ずかしいぞ
DB板だから基本的なWebの技術を知らない事は別に恥ずかしいことじゃない
恥ずかしいのは自分がどのくらい無知なのかを自覚せず斜め上のレスを繰り返してる事 お釈迦様の手のひらに乗って得意そうにしている孫悟空の図 ISSってもしかしてIISのことだったの?
Web周りの技術力と言われてWebSphereやOASを出してくるのもどうかと思うが比較対象にIISを入れるのはもっとどうかと思う OASが昔のものだと指摘しない、IISがたいしたものではないと思っている等、知識がおかしいな。 OASってまだ息してるの?
10年以上前に終わった製品だと思ってたんだが Oracle Application Server 10gを知っている人間が少ない。 >>921
そいつの時計の針は20年前で止まってる 逆に言えばその昔からアプリケーションサーバーやWebフレームワーク作る技術は持っていたってことじゃん。 >>925
10年前に使ったと言うかあるシステムの前提ソフトだったからセットアップしたことはある >>924
20年前ならアプリケーションサーバー製品の優劣が
ITベンダーのWeb周りの技術力を測る指標の一つにはなったかもしれんな
20年前ならね >オラクル信奉者は世情に疎くて技術力が低いやつが多くて嫌だよねー
これってさオラクル使い続けてるような会社はベンダー依存度が高く保守的なカルチャーのところが多いから
技術者が育ちにくかったり技術トレンドを把握してなかったりする傾向が強いんじゃないかな
そう考えると汎用機やCOBOLと同じ匂いがする理由もよく分かる >>928
COBOLerと違って自分たちがレガシー化してることに自覚がないから余計に質が悪い SQLのテストむずかしくないですか
分離できないし >>930
ちゃんとテストするのは本当に難しい。
SQLのテストをしない文化があるところだと、なんでもかんでもSQLに処理を押し付けて隠蔽して、手抜きをする。 >>928
OracleはNULLと空文字列の同一視をいい加減どうかしてほしいってのとやたら金がかかるところを別にすれば
そう悪いところはないと思うがな。
Oracleがレガシーだと言っている人たちはいったい何を使っているんだろう。もはやRDBMSじゃないのかな。 SELECTがFROMの前にくるのってくそめんどくさいよ
microsoftががまんできなくなってオレオレSQL作っちゃうだけあるよ >>932
日頃SQL-Server使ってるせいもあるけど例えばTO_CHAR()の書式修飾子とかなかなか慣れんわ
なんでまたトグル動作なんてわけわからん仕様にしたんだろ… 新しいフレームワークに対応させるのにどれだけ時間かけてるのかって… エドガー・F・コッドは後出しでNULLと空文字を分けた。数値型まで空を定義するように言ってしまったが、数値型の空数値については意味不明で、どの製品も無視している。 >>939
文字型は空文字列という値がない。空文字列のつもりでシングルクォーテーションでくくられた見た目が空文字列のものを、自動的にNULLとみなす仕様がある。 >>933
べつにOracleに限らず、SQLをどうにかしてほしいってのは確かに思う。
COBOLと同じで「英文に近ければ誰でも使えるんじゃね?」って発想していた時代の産物だしな。 >>941
俺もSQLの構文は好きじゃないけど、デファクトスタンダードになってしまうと、もう変えられないからなあ。 select句にcase式で数十個の分岐を書きたいのですが、
ルーチンのように先頭か末尾に書くことはできないのでしょうか。 >>943
ユーザー定義の関数にすれば?
SQLiteとかじゃなければSQLで関数定義できると思うけど >>943
見た目をすっきりさせたいという意図なら、WITH句を使う。
下記のようなサイトを参考にして
https://itsakura.com/sql-with Oracleは独自拡張でWITH句で関数定義できるからそのこと言ってるんじゃないの?
じゃなければ間違ったWITH句の使い方 その手のは言ったもん勝ちだな。
これだからOracleユーザーはw
これだからSQLServerユーザーはw
これだからMySQLユーザーはw
言われにくいのはPostgresくらいかな。 >>951
まーた文脈読めないレスしやがって
これだからAccessユーザーはww これだから他DBMSユーザーを貶すことしかできない奴はw >>932
RDBMS製品としてのOracleがレガシー化してるという話ではなく
Oracleを使い続けてるような組織や技術者がレガシー化してる(もしくはレガシー化しやすい)という話でしょ
当てはまらない会社がないわけではないけど傾向としては思い当たる節がかなりある OracleでSQL覚えたため、そのあと外部結合の書き方で苦労した わかる
(+)の書き方に慣れちゃった 結合条件は全てWHEREにないと落ち着かない 組織や技術者のレガシー化ってまた意味がよくわからん雰囲気ワードだな。
具体的にはどういう状態のことを言っているんだろう。 >>956
それOracleだけじゃなくて、他のRDBMSでもその構文は使える。
標準SQLの方がよい構文はそちらがスタンダードになっているだけ。
ここは本当に中高年しかいないなw >>955
MySQLで覚えてたらもっと酷いことになってた (+)構文がオラクル以外でも使えるって初耳だが
ググってもそれらしい情報出てこんし 少なくともSQL-Serverではdocsには載ってないから使えないと思う
秘密のコマンドでOracle互換モードとかあるのかも知れんがw >>960
PostgreSQL、Db2など。
そもそもどの製品も独特な外部結合構文を持っていて、Oracle Databaseだけが独特なのではない。 >>957
>Web周りの技術力ってISSとWebSphereとOASのどれが優れているかとかいう議論ならわかるが、
↑これがレガシー化
自覚がない本人かもしれんが レガシー化というのは時代の変化や環境の変化に対応できなくなってること
旧式化して時代遅れになってると言ってもいいが
簡単にはリプレースできないしがらみや機能や考え方が硬直的というニュアンスも含む
逆に硬直性の無いものはレガシーとは言わない
人に対して使う場合は時代遅れと老害を足して2で割ったものと思っておけばいい 943です、皆さん回答ありがとうございます
やりたかったのは、食品の販売だとすると、
イチゴや大根の商品コードを対して、果物や野菜、といった分類をCASE式でつけたいのですが、20行程度のSQLの冒頭に数十行のselect句があると頭でっかちに感じた次第です。 >>968
例えばイチゴの場合に果物か野菜かの判定をSQL文の中で行わせたいって事か? >>968
それは商品コードを管理するマスタに分類を持たすとか、判断用のビュー作とかするのが普通じゃないかと思うんだが
まあ、設計はスレ違いではあるが、設計見直すべきだと >>970
>>管理用のビュー
943です。ビューならいじりやすいですね。20年前にソフト屋さんに作って貰った販売管理で、データ取得用のビューがあります。ただ上のコード分類とて30か50個の商品コードのことです。規模が小さいのにオラクルなので他のソフト屋さんに驚かれます。 >>972
20年前ならOracleかSQL Serverの二択ですからね。 普通にPostgreSQLやMySQLも使われてただろ SQL SERVERですが decimalの最大桁数(Permission)とバイト数について
1 - 9桁 5バイト
10 - 19桁 9バイト
20 - 28桁 13バイト
29 - 38桁 17バイト
となってると思いますがデータの桁数が多少変動し不明確な場合、
極論各バイト数の最大(9桁、19桁、28桁、38桁)をとっておけば、
実際の桁数少なくてもバイト数も変わらないし無駄はないかなと思っているのですが、この考え合っていますでしょうか?
皆さんどうされていますか? >>968
それはCASE式じゃなく分類コードを管理するテーブルを作るべきケース
行と列の縦横変換はPIVOTとかの関数を使う
分類が変化しそうにもないなら既存の商品テーブルに分類コードのカラムを追加するのが望ましいが
なんらかの事情でそれが難しいようなら商品コードと分類コードの紐付きを管理するだけの別テーブルを作るのでも構わない >>976
バイト数以外で最大有効桁数を制限しておきたい理由がなければその方針でいいんじゃない
とりあえず9桁にしておくってみたいなケースはよくあるよ
PermissionじゃなくPrecisionね >>976
桁数は大きくしておいて、どうしても小さくしたいのなら、あとから変えればいいだけ。 日本円の金額項目なら、9桁は小さいから、よく考えた方がいい。 MAXが1億って、比較的小さい規模の企業ではないかな
個人商店でも溢れそうな気がする 仮に金額入れるとしても9桁で十分なユースケースはいくらでもあるだろう
smallmoneyとか何のためにあると思ってるんだ?
それに9桁ならMAXは約10億だぞ
大丈夫か? 馬鹿っぽいと言っておけば
自分の馬鹿さを隠せるとでも思ったのか 仕事の会話だったら、普通は9億いくつという言い方をする。約10億だと10億以上もあるということになり、認識がずれてしまう。 桁数の話してるんだから普通の人は約10億で最大九億九千九百九十九万九千九百九十九ってわかると思うんだが… 毎度赤っ恥かく原因はクソみたいなマウンティング精神にあることを気付こうな
いい年してそれじゃヤバいで with句とfromのサブクエリ、皆さんどのように使い分けていますか? WITH句は徐々に浸透しているから、WITH句を使わない決まりがないなら、WITH句はどんどん使うべき。 このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 670日 1時間 19分 11秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。