Skip to main content
Announcements
Introducing Qlik Answers: A plug-and-play, Generative AI powered RAG solution. READ ALL ABOUT IT!
cancel
Showing results for 
Search instead for 
Did you mean: 
tsuyoshi
Partner - Creator
Partner - Creator

ロードスクリプト内における特定の行と特定の行の時間計算


お世話になります。教えてください。縦のデータの時間差の計算が思いつきません。

時刻アクションログインしていた時間
7:10:00ログインNULL
8:00:45作業1NULL
10:00:50作業2NULL
13:34:54ログオフNULL

というcsvがある場合に、ロードスクリプト内でログオフの行にログインしていた時間をセットしたいのです。

ロード後

時刻アクションログインしていた時間
7:10:00ログインNULL
8:00:45作業1NULL
10:00:50作業2NULL
13:34:54ログオフ6:24:54

 

としたいのですが、こうのように縦のレコードにおいて、特定の時間から特定の時間を引くという処理はどのようにすれば可能でしょうか? お手数ですがご教示願えたら幸いです。

 

3 Solutions

Accepted Solutions
hka
Employee
Employee

下記スクリプトでどうでしょうか。

一応、作業者が複数いるという前提で記述してます。

日にちをまたぐ場合は、TimeStampを使用する必要があるのと時刻の変換処理を考えないといけないかと。

Sample:
LOAD * INLINE [
ID,時刻, アクション
1,7:10:00, ログイン
2,7:20:00, ログイン
1,8:00:45, 作業1
2,9:00:50, 作業2
1,10:00:50, 作業2
1,13:34:54, ログオフ
2,13:40:45, 作業1
2,14:24:54, ログオフ
];

Join
LOAD
ID,
時刻,
アクション,
time(if(Peek(アクション)='ログイン' and アクション='ログオフ',time(時刻)-time(peek(時刻)))) as ログインしていた時間
Resident Sample
where アクション like 'ログ*'
Order by ID;

 

View solution in original post

hka
Employee
Employee

 

下記のような形で可能です。

Sample:
LOAD * INLINE [
ID,時刻, アクション
1,7:10:00, ログイン
2,7:20:00, ログイン
1,8:00:45, 作業1
2,9:00:50, 作業2
1,10:00:50, 作業2
1,13:34:54, ログオフ
2,13:40:45, 作業1
2,14:15:45, 作業3
2,14:24:54, ログオフ
];

LOAD
time(if(アクション='ログオフ',time(時刻)-time(peek(時刻,No-LogNo)))) as ログインしていた時間,
*
;
LOAD
RowNo() as No,
ID,
if(アクション='ログイン',0,Peek(LogNo)+1) as LogNo,
時刻,
アクション
Resident Sample
Order by ID,時刻;

DROP Fields No,LogNo;

DROP Table Sample;

View solution in original post

hka
Employee
Employee

スクリプトはDB接続の場合のスクリプトの応用と思ってもらえればいいと思います。

DB接続の場合

LOAD * ;

SQL Select * FROM Table;

のようにLOADが「;」で終了して、後ろのSQL Selectの内容を取り込んでいます。

同じように

LOAD  * ;

LOAD * FROM Table;

という記述をすると下のLOADの内容を上のLOADで取り込むことができます。

Qlikでは下のLOADで新たに定義された項目を使用するのに、LOADを重ねて書くことができます。

このようにすると

LOAD A,B,A + B as C FROM Table;

LOAD  A,B,C,C*1.5 as D  Resident Table; 

のように一度ロードされたデータをもう一度Residentでロードするよりも

LOAD C*1.5 as D,

               *;

LOAD A,B,A+B as C FROM Table;

のように記述する方がスクリプトがシンプルになります。

 

今回の上のLOADは下のLOADで定義されたNoとLogNoを使用しています。

Noが全体の行数、LogNoが'ログイン'を0として、ログオフまでの行数を計算しています。

それで全体の行数からログオフの行数を引くことでログインの行数が何行目かを特定しています。

Drop Fieldsの部分をコメントアウトして、リロードし直してもらうと考え方がわかると思います。

この説明で大丈夫ですか?

View solution in original post

8 Replies
hka
Employee
Employee

下記スクリプトでどうでしょうか。

一応、作業者が複数いるという前提で記述してます。

日にちをまたぐ場合は、TimeStampを使用する必要があるのと時刻の変換処理を考えないといけないかと。

Sample:
LOAD * INLINE [
ID,時刻, アクション
1,7:10:00, ログイン
2,7:20:00, ログイン
1,8:00:45, 作業1
2,9:00:50, 作業2
1,10:00:50, 作業2
1,13:34:54, ログオフ
2,13:40:45, 作業1
2,14:24:54, ログオフ
];

Join
LOAD
ID,
時刻,
アクション,
time(if(Peek(アクション)='ログイン' and アクション='ログオフ',time(時刻)-time(peek(時刻)))) as ログインしていた時間
Resident Sample
where アクション like 'ログ*'
Order by ID;

 

tsuyoshi
Partner - Creator
Partner - Creator
Author

ありがとうございます!!

追加でご質問ですが、本件の場合、ログオン、ログオフの順番になっているはずなので一応それを確認したうえで1つ前の行であるログオン時刻を使うというものですが、peekで1行前ではなく、何かの条件によって2行前や3行前などにある任意の行(ログイン時刻)を見るということは可能でしょうか?よろしくお願いいたします

hka
Employee
Employee

Peek関数は行番号指定できるので、できると思いますがデータ詳細とと

条件がわからないと具体的な回答は難しいです、

tsuyoshi
Partner - Creator
Partner - Creator
Author

アドバイスありがとうございます。Whereで’ログ’のみに絞らず、縦に作業1や作業2などを挟んでいる場合、それを飛び越えて前のログインの行をpeekするということが可能か伺いたかったのです

一番はじめの質問に関する解決法としては ’ログイン’’ログアウト’で絞って1行前を見ることで、問題なくできるようになっています。peekのより高度な使い方として知りたかったので追加で質問させていただきました

hka
Employee
Employee

 

下記のような形で可能です。

Sample:
LOAD * INLINE [
ID,時刻, アクション
1,7:10:00, ログイン
2,7:20:00, ログイン
1,8:00:45, 作業1
2,9:00:50, 作業2
1,10:00:50, 作業2
1,13:34:54, ログオフ
2,13:40:45, 作業1
2,14:15:45, 作業3
2,14:24:54, ログオフ
];

LOAD
time(if(アクション='ログオフ',time(時刻)-time(peek(時刻,No-LogNo)))) as ログインしていた時間,
*
;
LOAD
RowNo() as No,
ID,
if(アクション='ログイン',0,Peek(LogNo)+1) as LogNo,
時刻,
アクション
Resident Sample
Order by ID,時刻;

DROP Fields No,LogNo;

DROP Table Sample;

tsuyoshi
Partner - Creator
Partner - Creator
Author

 

びっくりしました、なんだか天才のようなスクリプト

peekが前行だけじゃなく、前にも後ろにも行けることもわかり、最終的にはなんとなくやっていることが分かるのですが、このスクリプト自体が初心者の理解を超えています。すみません(;^_^A

まずinlineロードはもちろんわかります

次に突然LOAD time(if(アクション・・・・ これが突然出てくるのはどういうことでしょうか?NoもLogNoもまだ出てきてないのに・・・

そして最後のLOAD・・

本当に申し訳ありません。てっきりQVのスクリプトは上から順次、処理して下に降りてくると思っていました。私の言っていることが逆に素人すぎて変かも知れませんが、お手すきの際に、真ん中のLOADがまだNoやLogNoが出てきていない状況で一体何をしているのか?

また最後のLOADで「ログインしていた時間」が書かれていないのに、項目としてセットされてくるあたり、文章で解説いただけましたら非常に助かります。すみませんが宜しくお願いいたします。

 

hka
Employee
Employee

スクリプトはDB接続の場合のスクリプトの応用と思ってもらえればいいと思います。

DB接続の場合

LOAD * ;

SQL Select * FROM Table;

のようにLOADが「;」で終了して、後ろのSQL Selectの内容を取り込んでいます。

同じように

LOAD  * ;

LOAD * FROM Table;

という記述をすると下のLOADの内容を上のLOADで取り込むことができます。

Qlikでは下のLOADで新たに定義された項目を使用するのに、LOADを重ねて書くことができます。

このようにすると

LOAD A,B,A + B as C FROM Table;

LOAD  A,B,C,C*1.5 as D  Resident Table; 

のように一度ロードされたデータをもう一度Residentでロードするよりも

LOAD C*1.5 as D,

               *;

LOAD A,B,A+B as C FROM Table;

のように記述する方がスクリプトがシンプルになります。

 

今回の上のLOADは下のLOADで定義されたNoとLogNoを使用しています。

Noが全体の行数、LogNoが'ログイン'を0として、ログオフまでの行数を計算しています。

それで全体の行数からログオフの行数を引くことでログインの行数が何行目かを特定しています。

Drop Fieldsの部分をコメントアウトして、リロードし直してもらうと考え方がわかると思います。

この説明で大丈夫ですか?

tsuyoshi
Partner - Creator
Partner - Creator
Author

>という記述をすると下のLOADの内容を上のLOADで取り込むことができます。

>Qlikでは下のLOADで新たに定義された項目を使用するのに、LOADを重ねて書くことができます。

有難うございます。全然知りませんでした。

びっくりしています。

今までてっきり上から順に定義してqvdに一旦中間ファイルを吐き、それを再度読み直して順次処理を行っていました。本当にありがとうございました。(^^♪