SQLなら俺に訊け [無断転載禁止]©2ch.net
count(*)の*と、select * fromの*は同じでしょうか >>3
違うよ
select * from fooは、「fooテーブルの全カラム」という意味
count()の方は、
count(column_name)とカラム名を指定したときは、column_nameがnullではない行数が取得される
count(*)だとnullとか関係なしに全行数 >>3 >>4
ありがとう。なんとなく違う感じでうまく説明できなかったけど、>>4の通りだわ >>4
>column_nameがnullではない行数
column_nameがnullになる事が有るの? foo_id, bar_id_list
"1", "1,2,3"
"2", "4,5"
"3", "6,7,8"
これを
foo_id, bar_id
"1", "1"
"1", "2"
"1", "3"
"2", "4"
"2", "5"
"3", "6"
"3", "7"
"3", "8"
こう変換するクエリって書ける?
なるべく標準がいいけどポスグレ依存でも可 >>8
お前は秘密の合言葉を言ってない。
「お願いします。どうか教えて下さい」 再帰クエリでできました
SQLは業務で使うことも多いのにSQLスレに人がいないのは寂しいですね SQL初心者です。
複数のrowを一度に取りたいのですがどう書けばいいのでしょうか。
後述の(C)より効率のよい記述を探しています。
(なおRock54回避の為シングルクオートを全角に、またselectをカタカナに変更しています)
用途は掲示板で、以下のような「先頭と最近の5投稿」の取得が目的です。
https://mevius.5ch.net/tech/
環境はSQLiteです。SQLite依存で構いません。
単純には以下2クエリになりますが、
select * from thread order by no limit 1; // (A)
select * from thread order by no desc limit 5; // (B)
A-B間で更新されたときに過渡状態のデータが返ることを避けるため、一つに纏めたいのです。
SQLiteでは読み込みにはトランザクションが使えず、BEGIN/COMMITで囲んでブロック出来ません。
試行錯誤して一応以下のクエリは通るようですが、サブクエリが効率が悪く見えるのでもっと良い書き方を探しています。
セレクト from ’1234’ where no in (values(’1234’) union セレクト no from ’1234’ order by rowid desc limit 6); // (C)
ここで1234はスレッド名=スレッド最初の投稿Noです。
4chanのように板毎にNoが打たれており、スレ内のNoは飛び飛びになっています。
なお前側values部分もサブクエリにして先頭番号を取得する limit 1のサブクエリも書き方があれば教えてください。
(デバッグ時に使う)
これも出来ません。例えば、以下は通りません。
セレクト * from ’1234’ where no in ((セレクト no from ’1234’ limit 1) union セレクト no from ’1234’ order by rowid desc limit 6); // (D)
// limitはunionの後に、とエラーが出る
(A)+(B)は同時にデータも取得する為、(C)より効率がいいと考えています。
(データの順序が異なるが、簡単にカバー出来る範囲なので問題ない)
ただし(A)+(B)だと場合によっては中途半端なデータが返る時があり、これは避けたいのです。
なお初心者の為上記前提がいろいろ間違っているかもしれませんが、その辺はご指摘下さい。 SQLiteがreadでトランザクション使えないって、そうだっけ?
デフォルトがrepeatable readじゃないから勘違いしてるとかじゃなくて? >>13
そうなのかもしれませんが、それを変える方法が分かりません。
SQL自体はSQL92準拠らしいです。
http://www.sqlite.org/fullsql.html
ちなみにトランザクションのページはこちら。
http://www.sqlite.org/lang_transaction.html
なお、select自体は一つのトランザクションらしく、例えば上記(A)(B)を繋いで begin; commit;で囲むと、
「トランザクション中でトランザクションを開始出来ません」というエラーになります。
// Error: cannot start a transaction within a transaction ああすいません、これですかね?
PRAGMA read_uncommitted;
http://www.sqlite.org/pragma.html#pragma_read_uncommitted
ここの書き方だとよく分からないのですが、
デフォはSERIALIZABLEで、これをREAD UNCOMMITTED(true)にして、
さらに書き込み側をBEGIN EXCLUSIVEにしろってことですかね?
> After a BEGIN IMMEDIATE,
> no other database connection will be able to write to the database or do a BEGIN IMMEDIATE or BEGIN EXCLUSIVE.
> Other processes can continue to read from the database, however.
> An exclusive transaction causes EXCLUSIVE locks to be acquired on all databases.
> After a BEGIN EXCLUSIVE,
> no other database connection except for read_uncommitted connections will be able to read the database
> and no other connection without exception will be able to write the database until the transaction is complete.
> http://www.sqlite.org/lang_transaction.html あ、いや、違いましたね。
read_uncomitted は制限を緩和する方向でした。
まだ全貌を把握しておらず、ここら辺はすみません。
SQLiteはseriarizableを実装しているとは書いてありますが、デフォが何かはよく分かりません。
> SQLite implements serializable transactions
> http://www.sqlite.org/transactional.html
ただまあ、今のところ複数selectをトランザクションに指定する方法が分かりません。
多分単発のselectなら自動的にトランザクション化してます。 ちなみに記事は古いんですが、複数のselectをbegin/endで囲むことも出来るっぽいんですよね、、、
https://stackoverflow.com/questions/7349189/optimizing-select-with-transaction-under-sqlite-3
私が出来ないのは、こちらの環境の問題でしょうか?
PHP経由でのsqlite3.15.1と、コマンドラインの3.21.0の両方で駄目です。 >>12を取り下げます。
どうやら私の書き方が悪かったようで、別々に打たないといけないらしく、
そうすればあっさり出来ました。
どうもすいません。
参考にしたページは以下です。
http://d.hatena.ne.jp/hide-K/20090623/1245752394 このスレはデータベース板にいるやつのネタスレだな。
count(*)は慣習上、このように書いているだけ。 SQLは重いというイメージが頭から離れない
またとってくればいいだけなんだが
どうしても一度取得してきたデータを使いまわしたくてプログラムがぐしゃぐしゃになる ん?普通そうだが、何でぐしゃぐしゃになるのかが分からん スコープの長い変数をずっと持ってないといけないから
メソッドの引数がふえて
だから作ったメソッドが使いづらい 何の言語か知らんけど、構造体とかクラスで使えば良いのでは?
取り敢えず一度取得してきたデータは使いまわすのが基本
その都度発行とか有り得んから、使いまわせるように工夫すべき えー
せっかくDB側でSQLキャッシュしてくれる機能もってんのに
プログラムでもまたキャッシュの仕組みつくるん? そんなの使い方に依るでしょ
SQLiteのが遥かに適してるのにネットワーク型拵えてるアンチパターンはかなり見るが
この逆は滅多に見ない、SQLiteは玩具過ぎて使えないと言ってる使えない人間はかなり居る AccessでのVBAの開発の話なんだが、他言語含めて飽きるほどコード書いてきたという人がSQLで書くようなことはしないと言うんだ。
デザインビューでクエリー作るんだって。
俺とは余りに文化が違うんだが、これって俺がおかしいのかな。
それとも彼がビックマウスなのかどっちだと思う? Accessは知らんが。
これ見る限り、そのやり方もありだろう。
https://www.microsoft.com/japan/office/previous/xp/suminaka/access/sousa/1/sousa1_15_2_honbun.htm
http://www.microsoft-access.net/start/query-2.html
> 俺とは余りに文化が違うんだが、これって俺がおかしいのかな。
> それとも彼がビックマウスなのかどっちだと思う?
お前がおかしいことは確定だが、(ただしお前が言っている意味ではない)
彼がビッグマウスかというのは意味が分からない。(だからお前はおかしい)
そもそも、やり方は一つじゃない。どっちが正しいという考え方がおかしい。
そいつにとって効率がいい方法を使えばいいだけ。
この画面通りに動くのなら、クエリ結果画面を見ながらGUIでプログラミングできる。
手打ちでSQL書いて動かしてデバッグするより早いのは確かだよ。
同様な物に、VSのフォームデザイナがある。
さすがにあれを全部手打ちする奴はいないと思うが、技術的には出来る。
あれは毎回Form1.hをパースして表示しているだけだから。
ただしパーサは自動出力の結果を読み込む前提で全くロバストではないから、
少しでもエラーがあったら止まってしまい、それ以降デザイナが使えなくなる。
だから手打ちは推奨されていない。とはいえ、出来る。 以下は推測になるが、、、
おそらくAccessも同様に、自動作成クエリを読み込んで表示するようになっていると思われる。
その場合、手打ちでクエリを作成されると、そこでエラーが発生した場合、クエリデザイナが使えなくなってしまう。
だから、プロジェクトとして、「クエリデザイナしか使うな」みたいな縛りはあり得る。
局所的に手打ちでクエリ書いたとして、そこがデザイナ側に読み込まれないのならエラーにはなりようもないが、
後の人が手打ちでクエリを書けない人ならメンテナンスが出来なくなってしまう。
ただし、デザイナに頼りすぎると後々色々大変になるので、
中にはデザイナは最低限しか使うな、という人もいる。
フォームの場合は「イベントをデザイナで書くな」みたいになるわけだが、
Accessの場合は「クエリをデザイナで書くな」になるんじゃないかな?
だから、そこはやり方の問題だ。
どっちが正しいかではなく、どちらを選ぶかだ。当然、チームの他の人員のスキルも考慮しないといけない。
Accessの場合にどちらが主流派なのかは俺は知らない。
ただな、SQLってのはDB用アセンブラみたいなもので、
実際、そんな物をいちいち手打ちしてたら効率は上がらないだろ。
SQLは未来永劫手で書くものだ、と思っているのならお前がおかしい。
(俺は使ったこと無いが)ORMはそこを完全に隠蔽していて、SQLなんて当然自動生成で、
プログラマがいちいち書くはずもないだろ。(現実にはそうでもないらしいが、少なくともそこを目指しているだろ)
ただし、スキルとしては当然読めた方がいいし、手でも書ける人が手抜きする為にデザイナを使うのが本来は正しい。
だから君の立ち位置は間違ってはいない。
君はデザイナを覚えて、君のプロジェクトではどちらを使うか判断すればいいだけ。
既にあるプロジェクトに参加するなら、そのプロジェクトの流儀に従うしかない。
繰り返すが、俺はAccess知らないから、Accessの文化については他の人を待て。 SQLでJOIN等の結果に別名を付けるエイリアスってありますか? >>32
解決しました。ありがとうございました。
ところでミックさんの本は名著だと思いますが、セルコを読んでみたら、むちゃくちゃわかりやすくて驚きました。
プログラミングの本は洋書に限るという主張はかなり当たっていますね。 日本語でもあれだけの容量を割ければわかりやすく書けるのでは。
日本語の技術書って2000部出ればヒットの部類だって言うし
国産で6000円の本がどれだけ売れるやら(=コストがかけられるか)
楽器の教則とかも似た感じだが
勢い初心者向けの入門書が多くなり、レベルの高い本はページ数が足らなくて
分かる人だけ分かってとか分かってる人が知識の確認に使う本が多い気がする
個人的には洋書(の翻訳)は
「もうxxでxxする必要はないのです!」
みたいな無駄な例えとかジョークが多くてちょっとイラっとする時がある SQLで超高速スクロールシューティングゲームを作りたいのですがどこから勉強したらいいのかわかりません SQLの勉強をした後に普通の手続き型言語の勉強をすると楽ちんさに驚く。SQLは難しいわ。 ミック氏の著書にある「WHERE句で分岐させるのは素人、
プロはSELECT句で分岐させる」を職場で実践したら異常
者扱いされて追放されたよ [tbl]
key
-----
A
B
C
D
こんなテーブルがあって、
SELECT key
FROM tbl
ORDER BY CASE WHEN key = 'B' THEN 1
WHEN key = 'A' THEN 2
WHEN key = 'D' THEN 3
WHEN key = 'C' THEN 4
END;
このSQL文で並べ替えができるのはなぜでしょうか? n+1問題ってなんやねん
パフォーマンス低下したら何がいけないの? 文字列を追記するにはどうすると良いのでしょう?
これだと上書きされてしまいます。
どうすると良いのでしょう?
$sql = 'update imglistdb set mcategory = ? where id = ?';
$stmt = $dbh->prepare($sql);
$flag = $stmt->execute(array($w, $id));
if ($flag){
print('データの更新に成功しました<br>');
}else{
print($id.'のデータの更新に失敗しました<br>');
} サマータイムが導入されたとしてUTCで時刻が記録されてテーブルで
今日の分の売り上げを集計する場合どうするのが正しいですか? SQLの構文ってなんであんなクソだらけなものが採用され続けているの?
insertのintoとかupdateのsetとかいらないし
updateでwhereを指定し忘れたら全レコードが更新されるのとか超危険だし
updateはID指定→値指定で更新っていうのが直感的にやりやすいのに
whereを最後に持ってこないといけない仕様のせいでid指定が最後になるし
カラムと値の指定の仕方も一貫性がないし
後方互換性としてあれらのコマンド"も"使えるならまだわかるけど
あれらのコマンド"しか"使えないとかこの業界頭おかしいんじゃないの 言いたい事は分かるし別に否定はしないのだが、糞でも広まって使われてる以上それに従わざるを得ないのさ
JSと一緒だよ フェールセーフの仕組みはインターフェースの実装レベルでなんとかしてねってことなんじゃないの データの持たせ方を誤ってしまって、
カラム定義
時間,val1,val2,val3・・・
ってなってるんですが、val1からvalnで最大値を取りたい場合、どのようにアプローチするのがスマートですか? 時間がユニークじゃないどうしようもない状態なら
とりあえずコレでいけるハズ
select
max(ahox.time_),
max(ahox.max_val)
from
(
select rowid, time_, val1 as max_val from aho
union all
select rowid, time_, val2 as max_val from aho
union all
select rowid, time_, val3 as max_val from aho
...
) ahox
group by
rowid
時間がユニークならrowid(DBMSが内部的にテーブルにもたせてる行の識別値)みたいなもんは使う必要ない
使う必要があるならrowidはDBMSごとに違うからあとは調べなさい 運用方法のアプローチとしては
とりあえず一回全抽出してテーブルを作り直したほうがいい
こんな感じのワークテーブルをマニュアル作業で一旦作る
id, eventno, 時刻, 項目名, 値
eventnoの部分にはとりあえずrowidつっこんどく
で、idはただのシリアル値
システムがこの形式のテーブルに落とせる運用にすれば
それからはすぐに最大値がとれるようになる
そうなるまで毎回ワークテーブル作って最大値とるようにすればいい
それまではマニュアル作業で自分でテーブルをつくりなおす
失敗したヤツがちゃんと責任もってやるようにな エクセルの行列を、そのまま表定義にする、馬鹿が多い
列に製品番号があれば、列1・列2・列3 と定義しよる。
それで製品番号が増えるたびに、列を増やしていくw
頭おかしいw >>54
>>55
お二人共、ありがとうございます。
テーブル再定義も含め、まずは54さんの手法でこの場は凌いでみます。 >>57
同一IDだた。いずれにしてもサンキューです。 DBの検索速度ってPC上ではかなり遅いみたいですけど
大手Webサービスはどこも一瞬で結果を返してくれますよね
あれは単にサーバーのスペックが凄いから早いんですか?