こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

上から何番目か。

$sql = "select * from table_namae where no = 115 order by jikan desc";

の場合、上から何番目か知る方法がわからん。
時間でソートして、そのnoが上から何番目かを知りたい。
もちろん、レコードの値も欲しい。

NO 115を検索して
 タイトル 名前 パスワード
 → 時間でソートして上から?番目

noはPRIMARYで重複する値はなく常に一つだけ。
SQLで値を得る事は、無理?
noは特にその都度変わるので、limitは使えないと思うんですが。

PHPなら、ソートして最初から希望のナンバーまでのレコードを取得。
$i = 0;
 while($col = mysql_fetch_array($rst)){$i++;
if(希望のナンバー){
print "$i番目";
print "タイトル、名前さん。"} }

これでも、取得できるけど、無駄なループになるし。

投稿日時 - 2005-07-18 00:26:25

QNo.1520509

困ってます

質問者が選んだベストアンサー

ちょっと、タイプミスが、

SELECT T1.no, T1.name, T1.title, T1.jikan, COUNT(T2.no) as bangou
FROM table_namae as T1,
table_namae as T2
WHERE T1.no = 115
AND T1.jikan >= T2.jikan
GROUP BY T1.no;

こっちです。
質問の意図を読み間違えてなければ、これでばっちり。

投稿日時 - 2005-07-18 13:11:06

お礼

いろいろといじった結果。
挙動の内容が分かりません。
いや、結果はokなンすけど。

SELECT T1.no, T1.name, T1.title, T1.jikan,
//上記のフィールドを表示させる
COUNT(T2.no) as bangou
//bangouをカウントする 
//↑なにをカウントしてる?
//理屈としては、T1.jikan >= T2.jikanの場合はカウントしてるんだろうけど
//と、言う事はループしてる?どこが?なにが?
//COUNT(*)としないのは、重さ軽減のため?

FROM table_namae as T1, table_namae as T2
//テーブルをT1,T2とする

WHERE T1.jikan >= T2.jikan
//T1.jikan >= T2.jikan を比較ループしてる?
//WHERE文って、ループしないですよね?
//検索上から下まで1回では、無理な気もします。

GROUP BY T1.no
//GROUPでまとめる
ORDER BY bangou;
//bangou順にソート

WHERE T1.jikan >= T2.jikanで抽出して、COUNT(T2.no)してるんだろうけど、SQL側の挙動が最終的に分かりません。

本来の問題は解決しているのですが、知識のある方どなたでもいいので、教えて頂けると、すっごい助かります。^^;

投稿日時 - 2005-07-18 14:43:18

このQ&Aは役に立ちましたか?

3人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

付き合ったついでに・・・

SQLを考えるときには、ループなどで考えてはいけません。
集合的に考えると話がすっきりします。

まず、FROMに書かれている全てのテーブルの直積(組み合わせ)を考えます。

この例だと、T1とT2の全ての行の組み合わせです。
行数は、テーブルの行数を全て掛け合わせたものになります。

次にWHEREの条件で行を絞り込みます。

次にGROUP BYで書かれた項目でグルーピングを行います。

その結果行をHAVINGで絞り込みます。

最後にORDER BYで並べ変えます。

COUNT(T2.no)はCOUNT(*)でもかまいません。
ほとんど同じ意味です。
本人はあまり意識しないで書いてます。

この例では、noは主キーですので、NULLは入っていないでしょうから、同じ値になりますね。

COUNT(no) は、noがNULLの行を数えないのに対し、COUNT(*)は、全てを数えると言う違いがあります。

投稿日時 - 2005-07-18 17:38:45

お礼

直感的に分かったのが、”集合的”という言葉です。
「テーブルの行数を全て掛け合わせたものになる。」
なるほど、これでおぼろげながらSQLのデータ構造が分かった気がします。

WHEREの条件、GROUP BY、HAVING、ORDER BYの順番も参考になりました。
まだ、SQL文も手探りで、とりあえず作成。
ダメなら、位置を変えてみたり別の記述を試してみたり、結果を眺めてあってそうなら理由を考える。
okそうなら、PHPに書くという手順です。

本当にありがとうございました。^w^

投稿日時 - 2005-07-18 19:04:02

ANo.4

T1のnoを115にしてますので、T1からは、noが115の行だけが、抽出されます。
T2は、T1のnoよりnoが小さいか等しい行だけが、抽出されます。
したがって、GROUP BYを行う前は、T1のnoが115の行と、T2のnoが115以下の行が存在します。

T1.no T1.name T1.title T1.jikan (T2.no) T2.jikann
115 foo var 110 1 10
115 foo var 110 40 50
115 foo var 110 115 60

T2.name と T2.title は関係ないので省略しています。

これを、T1.no でグループ化すると、答えが出ます。
T1.no は、グループ化項目なので関係なし、T1.name、T1.title、T1.jikanは、全行で同じなので問題無しです。
T2.noは表示しないので、これも問題ありません。

これで、分かりました?

投稿日時 - 2005-07-18 17:27:51

お礼

まだ説明はできませんが、感覚的に分かったような気がします。
PerlやPHPとは、SQLは一線を画しているンすね。
当たり前か。^^;
毎回、フィーリングでプログラムを作っているンすけど、(たぶんこの方が処理が早い、メモリー的にも少ない、、、はず)、こういう細かな設定やシステムには、気になってしまって。
大変参考になりました。
ボクのSQLの礎の一つとなると思います。

投稿日時 - 2005-07-18 18:55:39

ANo.2

こんなSELECT文で書けます。

SELECT T1.no, T1.name, T1.title, T1.jikan, COUNT(T2.no) as bangou
FROM table_namae as T1,
table_namae as T2
WHERE T1.no = 115
AND T1.jikan >= T2.jikann
GROUP BY T1.no;

投稿日時 - 2005-07-18 12:34:05

お礼

やっぱり、すごい人もいるものです!!
できました。
このスクリプトでは一行だけでなく、T1.no = 115 AND をはずせば、すべての上からの番号が表示できます。

この文は、あと半年くらいはボクには書けそうもありません。
GROUP BYか、Havingかいろいろ試してはみたのですが、うまくいきませんでした。
テーブル名に仮の名前を付けて比較する事もできるんですね。
大変参考になりました。

投稿日時 - 2005-07-18 13:46:24

ANo.1

PHPと絡めますが、

$sql = "select * from table_namae where no <= 115 ";
$rst = mysql_query($sql);
$rows = mysql_num_rows($rst);

とすれば数が出てきますね。

投稿日時 - 2005-07-18 10:53:36

補足

mysql_num_rowsで出るのは、配列の総数。
私が知りたいのは、

no□name□title□jikan
1□一太郎□最初に□110
2□次郎□次ぎに□160
3□佐武郎□三番□95

で、時間でソートしたもののnoの上からの何番目という事です。
ソートすると、こうなります。
3□佐武郎□三番□95
1□一太郎□最初に□110
2□次郎□次ぎに□160

ソートしたものをnoの1で検索すると、2番目となります。
ソートしたものをnoの2で検索すると、3番目となります。
このnoが変わった時の、上から何番目がしりたいのですが。
mysql_num_rowsだと、3が出ます。
3つくらいなら、すべてを読み出してループしちゃえばいいんだけど、MySQLで分かれば、その方が早いかと。
ないですかね?

投稿日時 - 2005-07-18 12:25:25

あなたにオススメの質問