みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。
1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)
You are not logged in.
Pages: 1
お世話になっております。
ソート機能ですが「レコードをフィールド順でソート」を使用するとアクティブなフィールドでソートできるかと思うのですが、
「レコードのソート」のように「レコードをフィールド順でソート」で複数のソートを一括で行うことは可能でしょうか。
表型式での話ですか。
複数キーにしたソートは、その延長ではできません。
Offline
表型式での話ですか。
複数キーにしたソートは、その延長ではできません。
例えばですが、ソートしたいフィールドが2つあったとして、
スクリプトで1度目のプライオリティソートした後に、レコードの順番をナンバリング(ナンバリングは桁ぞろえする)して保持し、
2度目のセカンドソートして、レコードの順番をナンバリング、
1度目と2度目のナンバリングした順番を合体して「レコードをフィールド順でソート」すると機能するでしょうか。
単純なナンバリングではちょっと無理でしょうね。
1回めのソートで、次のようにナンバリングしても、
A a 100
A f 200
A b 300
B c 400
B d 500
2回めのナンバリングで、
A a 101
A b 302
B c 403
B d 504
A f 205
となるでしょうが、この順ではないです。
フィールド内容そのものを桁を揃えて合体させるのがいいのでは。
または、ナンバリングのフィールドを消去しておいて、Text1のソート後、
let (
$t = case ( get ( レコード番号 ) = 1 ; Text1 ; UniqueValues ( list ( Text1 ; $t ) ) ) ;
number * 100 + ValueCount ( $t )
)
という計算式でナンバリングを全置換し、で次にText2でソートして、
let (
$t = case ( get ( レコード番号 ) = 1 ; Text2 ; UniqueValues ( list ( Text2 ; $t ) ) ) ;
number * 100 + ValueCount ( $t )
)
という計算式で全置換していくとナンバリングができます。(カテゴリー数がそれぞれ100以内の場合)
ただ、そこまでするなら、普通のソートした方がいいのでは。
Last edited by Shin (2024-01-24 20:59:05)
Offline
最初のナンバリングを単にレコードの並び順に振るのではなく、
ソートしたフィールドの値が同じグループごとの順に振っていけばいいですよね。
それにはソートしたフィールド名を得る必要がありますが、条件が分かりません。。
Offline
複数のフィールド名をテキストで指定して、その順にソートする仕組みを作ってみました。
追加するフィールド3個
ids 集計 主キーの一覧
sorted テキスト グローバル(次の計算フィールドで使う、グローバル変数でも可)
sorter 計算 非保存 Position(sorted;主キー;1;1)
ソートするサブスクリプト
フィールド設定「sorted;ExecuteSQL("
SELECT \"主キー\"
FROM \"テーブル\"
WHERE \"主キー\" IN('" &
Substitute ( テーブル::ids ; ¶ ; "','" ) &
"')
ORDER BY " &
Get(スクリプト引数)
; "" ; "" )
」
レコードのソート「記憶する(sorterの昇順)」
このサブスクリプトを、ソートしたいフィールドを引数にして呼び出します。
引数は、フィールド名をQuoteしてカンマで連結
Quote("t1") & "," & Quote("t2")
降順にしたい場合はDESCを付ける
Quote("n1") & "," & Quote("t2") & " DESC," & Quote("t1")
※現在のテーブルのフィールドでしかソートできません。(SQLを複雑にすれば複数テーブルでも可能でしょう)
※IN()を使って対象レコードの主キーのリストをSQL文に埋め込んでるので、上限がどのくらいかな。
※非保存計算フィールドでソートするので、上記の上限とどっちがボトルネックになるか。100レコードぐらいでは瞬時に終わりましたが
複数のフィールド名をテキストで指定して、その順にソートする仕組みを作ってみました。
追加するフィールド3個
ids 集計 主キーの一覧
sorted テキスト グローバル(次の計算フィールドで使う、グローバル変数でも可)
sorter 計算 非保存 Position(sorted;主キー;1;1)ソートするサブスクリプト
フィールド設定「sorted;ExecuteSQL("
SELECT \"主キー\"
FROM \"テーブル\"
WHERE \"主キー\" IN('" &
Substitute ( テーブル::ids ; ¶ ; "','" ) &
"')
ORDER BY " &
Get(スクリプト引数)
; "" ; "" )
」
レコードのソート「記憶する(sorterの昇順)」このサブスクリプトを、ソートしたいフィールドを引数にして呼び出します。
引数は、フィールド名をQuoteしてカンマで連結
Quote("t1") & "," & Quote("t2")
降順にしたい場合はDESCを付ける
Quote("n1") & "," & Quote("t2") & " DESC," & Quote("t1")※現在のテーブルのフィールドでしかソートできません。(SQLを複雑にすれば複数テーブルでも可能でしょう)
※IN()を使って対象レコードの主キーのリストをSQL文に埋め込んでるので、上限がどのくらいかな。
※非保存計算フィールドでソートするので、上記の上限とどっちがボトルネックになるか。100レコードぐらいでは瞬時に終わりましたが
返信遅くなってしまい、申し訳ございません。
ExecuteSQLを使用したことないので仕組みが全く理解できていないのですが、
例えば、「ファースト」「セカンド」「サード」という3つのフィールドがあったとして、
これらを全て昇順でソートする場合は、
Quote(ファースト) & "," & Quote(セカンド) & "," & Quote(サード)
という計算式で結合し、変数に入れて、スクリプト引数として、
フィールド設定「sorted;ExecuteSQL("
SELECT \"主キー\"
FROM \"テーブル\"
WHERE \"主キー\" IN('" &
Substitute ( テーブル::ids ; ¶ ; "','" ) &
"')
ORDER BY " &
Get(スクリプト引数)
; "" ; "" )
」
に渡すということでしょうか。
大変恐縮ではございますが、ご教示の程宜しくお願い致します。
「フィールド名をテキストで指定」なので、
Quote(ファースト)
ではなく
Quote("ファースト")
です。
ソートのスクリプトと違ってフィールド名がスクリプトに組み込まれないのがミソですので。
逆に、フィールド名を変更した場合は自動的に修正されないので要注意です。
「フィールド名をテキストで指定」なので、
Quote(ファースト)
ではなく
Quote("ファースト")
です。ソートのスクリプトと違ってフィールド名がスクリプトに組み込まれないのがミソですので。
逆に、フィールド名を変更した場合は自動的に修正されないので要注意です。
ありがとうございます。
フィールド設定の計算式についてですが、
「主キー」や「テーブル」という文字は環境で使用しているフィールド名やテーブル名に当てはめるということでお間違いないでしょうか。
例えば主キーのフィールド名が「No」でテーブル名が「MainTable」だとすると
フィールド設定「sorted;ExecuteSQL("
SELECT \"No\"
FROM \"MainTable\"
WHERE \"No\" IN('" &
Substitute ( MainTable::ids ; ¶ ; "','" ) &
"')
ORDER BY " &
Get(スクリプト引数)
; "" ; "" )
」
になるということでお間違いないでしょうか。
主キーが数字だと、シングルクオートは不要になります。
テキストの場合囲みが必要
IN('a','b','Z')
数値の場合囲みは不要
IN(1,2,9)
という風になりますので。
SQLで、対象レコードの主キーのリストを指定したソート順でソートしてグローバルフィールドに入れ、
FMのソートはその結果のリストの内での主キーの位置でソートする、という仕組みです。
なので、主キーがただの数字(またはテキストでも主キー同士で部分一致する場合)だとうまくいかないですね。(1の位置を計算したつもりで11の位置を得てしまう可能性がある)
デフォルトのUUIDを使って実装してました。
そういう場合は、終端記号を追加するように、例えば
"#"&
ExecuteSQL(
~~~
; "" ; "#" ) & "#"
として、sorterの計算式を
Position(sorted;"#"&主キー&"#";1;1)
のようにすればいいかな。(テストしてません)
主キーが数字だと、シングルクオートは不要になります。
テキストの場合囲みが必要
IN('a','b','Z')
数値の場合囲みは不要
IN(1,2,9)
という風になりますので。SQLで、対象レコードの主キーのリストを指定したソート順でソートしてグローバルフィールドに入れ、
FMのソートはその結果のリストの内での主キーの位置でソートする、という仕組みです。
なので、主キーがただの数字(またはテキストでも主キー同士で部分一致する場合)だとうまくいかないですね。(1の位置を計算したつもりで11の位置を得てしまう可能性がある)
デフォルトのUUIDを使って実装してました。そういう場合は、終端記号を追加するように、例えば
"#"&
ExecuteSQL(
~~~
; "" ; "#" ) & "#"
として、sorterの計算式を
Position(sorted;"#"&主キー&"#";1;1)
のようにすればいいかな。(テストしてません)
どうしても計算式で返す値が「?」になるのですが、ご教示いただけますでしょうか。
・「No」は数値のシリアル番号で管理しています。(重複はありません)
・テーブルは「MainTable」という名前です。
・「$list」は「1,2,3,・・・」で「No」の集計です。
・「$kekka」は「"MainTable::ファースト","MainTable::セカンド"」というフィールド名が代入されています。
ExecuteSQL ( "SELECT \"No\"
FROM \"MainTable\"
WHERE \"No.\" IN(" & $list & ")
ORDER BY " &
$kekka ; "" ; "")
「WHERE \"No.\"」は「WHERE \"No\"」です。失礼いたしました。
先に書きましたように、主キーですから「重複がない」のは当然ですが、部分一致するとPosition関数で破綻しますから、
>・「$list」は「1,2,3,・・・」で「No」の集計です。
この場合
>$kekka ; "" ; "")
ではだめです。
まずはSQLの結果を見るために、
>・「$kekka」は「"MainTable::ファースト","MainTable::セカンド"」というフィールド名が代入されています。
これを直してください。テーブル名が入っててはだめです。
完全修飾でなくフィールド名だけにしてください。
SQLでテーブル名を付ける場合は::でなく.区切りになります。
"table"."field"
先に書きましたように、主キーですから「重複がない」のは当然ですが、部分一致するとPosition関数で破綻しますから、
>・「$list」は「1,2,3,・・・」で「No」の集計です。
この場合
>$kekka ; "" ; "")
ではだめです。まずはSQLの結果を見るために、
>・「$kekka」は「"MainTable::ファースト","MainTable::セカンド"」というフィールド名が代入されています。
これを直してください。テーブル名が入っててはだめです。
完全修飾でなくフィールド名だけにしてください。
SQLでテーブル名を付ける場合は::でなく.区切りになります。
"table"."field"
「$kekka」を"table"."field"の形に修正することで計算式の結果が「?」ではなくなりました。ありがとうございます。
しかし、グローバルフィールド(sorted)にフィールド設定をした後に「sorter 計算 非保存 Position(sorted;主キー(当方では「No」フィールド);1;1)」
を昇順にしたレコードのソートを行ったのですが、ソートが上手く機能しません。
主キーを数値にしていることが問題なのでしょうか。
そのことは、#10に書いてあります。
情報が整理できておらず、申し訳ございません。
記載の通り修正し、グルーピングされるように修正されました。ありがとうございます。
しかしファイルメーカーのデフォルト機能でソートした時と順番が異なりました。(「風景」「歴史」の順番が、「歴史」「風景」になってしまいます。)
何か考えられることはありますでしょうか。それとも私の設定が間違っている可能性が高いのでしょうか。
度々申し訳ございませんが、ご教示の程、お願い致します。
あちゃあ。英字と数字フィールドでしかテストしてませんでした。
FileMaker SQL は、Unicode バイナリソート順を使用します。これは言語のソートやデフォルトの言語のニュートラルなソート順で使用される FileMaker Pro のソート順とは異なります。
まさかFMの索引が使われないとは、知りませんでした。
索引が使える方法を考えないとだめですね。
「FileMaker Data API を実行」なら索引順でソートすると思ったんですが、どうもそうではない?
この機能は取得するフィールドを指定できないので、SQLより面倒です...
そういうことだったんですね。
かっこ悪いやり方かもしれませんが、
やはり昇順や降順でグルーピングを繰り返すのがよいのでしょうか...
Javascriptだと日本語ソートもできるようなのでWebビューアでやらせたらどうかと思いましたが、対象レコードのデータを全部送るのは結構手間がかかりそうです。
スクリプトの「レコードをフィールド順でソート」だとフィールド1つしかソートできませんが、表形式だとできるので、
ソートさせたいフィールドだけ含めた表形式レイアウトを作っておくとかですかねえ。
Pages: 1
[ Generated in 0.009 seconds, 9 queries executed - Memory usage: 569.66 KiB (Peak: 590.2 KiB) ]