質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

Q&A

解決済

2回答

413閲覧

結合しようとするテーブルのある行の日時が、結合されるテーブルの複数行の連続日時に挟まれた行に結合する検索式

satou

総合スコア19

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

0グッド

0クリップ

投稿2023/09/04 03:42

編集2023/09/04 04:00

実現したいこと

入室管理をマイクロソフトのsql で管理しているところ、入室をしたユーザーIDと、その際に使ったカードIDと、その時刻の一覧を取得したい。

欲しい出力

secom_iduseridreg_dt
100userA2023-01-10 1:00:00
100userA2023-01-20 1:00:00
100userA2023-01-30 1:00:00
100userB2023-02-10 1:00:00
200userC2023-02-10 2:00:00
100userB2023-02-20 1:00:00
200userC2023-02-21 2:00:00
100userD2023-03-10 1:00:00

前提

テーブルの定義

カード利用記録テーブル:t_secom
  • セコムカード(以下、単にカードと略します)の入室時刻を記録したテーブルで、列は、カードID、入室時刻があります。
  • カードを読み取り機にかざすたびに、カードID、入室時刻がこのテーブルにinsert されます。
  • なお、ハードウエア上の制約により、この2つの情報しか取得できません。

テーブル名:t_secom

列名type
カードIDsecom_idint
入室時刻reg_dtdatetime

データ例

secom_idreg_dt
1002023-01-10 1:00:00
1002023-01-20 1:00:00
1002023-01-30 1:00:00
1002023-02-10 1:00:00
2002023-02-10 2:00:00
1002023-02-20 1:00:00
2002023-02-21 2:00:00
1002023-03-10 1:00:00
カード貸与管理テーブル:m_secom_user
  • カードを貸与した日時のテーブルで、列は、カードID、ユーザーID、貸与日時があります。
  • カードの貸与があるごとに、カードID、ユーザーID、貸与日時がこのテーブルにinsertされます。
  • なお、このテーブルには、貸し出した日時の情報はありますが、返却した日時の情報は持っていません。
  • また、カードの返却があると、そのカードは管理者に貸与したという概念で管理しています(つまり、常に誰かにカードを貸与している)。

テーブル名:m_secom_user

列名type
カードIDsecom_idint
ユーザーIDuseridvarchar(20)
貸出日時lending_dtdatetime

データ例

secom_iduseridlending_dt
100userA2023-01-01 1:00:00
100userB2023-02-02 2:00:00
200userC2023-02-05 5:00:00
100userD2023-03-03 3:00:00

発生している問題・該当のソースコード・試したこと

カードを使いまわししていますので、下記のように、単純にテーブル結合をすると、入室時刻に対して複数のユーザーIDが表示されます。

sql

1select 2* 3from 4t_secom 5left join m_secom_user on m_secom_user.secom_id=t_secom.secom_id 6and t_secom.reg_dt >m_secom_user.lending_dt

文章で説明すると、結合しようとするテーブル(m_secom_user )のある行の日時(lending_dt)が、結合されるテーブル(t_secom)の複数行の連続日時(reg_dt)に挟まれた行に結合する検索式が欲しいのですが、これを達成するには、m_secom_userの各行に返却した日時の情報を作り出す方法が必要かと思いますが、この部分が皆目つかないです。

調査したこと

sql 日付とidのテーブル 日付とidとuserのテーブル 結合
こちらのキーワードで検索しましたが、
https://teratail.com/questions/15028?link=qa_related_pc_sidebar
こちらのサイトを見つけることしかできませんでした。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

m_secom_userを参照する為のlending_dtを、生成した後に結合するのが効率的でしょう。

SQL

1select reg.*, usr.userid 2from ( 3 select * 4 ,(select max(lending_dt) from m_secom_user 5 where secom_id=t_secom.secom_id 6 and lending_dt <= t_secom.reg_dt 7 ) usr_lending_dt 8 from t_secom 9 ) reg 10 left join m_secom_user usr 11 on usr.secom_id=reg.secom_id 12 and reg.usr_lending_dt = usr.lending_dt

投稿2023/09/04 05:56

編集2023/09/04 06:01
sazi

総合スコア25430

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

satou

2023/09/04 07:12

回答ありがとうございます。エラーなく、こちらの希望の検索結果が出ました。
guest

0

欲しい情報は「元のt_secomに、カラム1列(実際に使用したuserid)を追加したテーブル」です。
そして単純な一致条件ではないので実テーブル同士のjoinでは表現しにくい……ということなので

  • 結合するテーブル(useridを含む方)をサブクエリで導出したテーブルにする
  • 元のt_secomをセレクトして、相関スカラサブクエリで1カラム(userid)だけ追加する

等で解決できると思います。


たとえば相関スカラサブクエリであれば
ただのselect t.* from t_secom as t; にカラム追加するサブクエリとして
「利用記録のとある1行に対して、同一のsecom_id かつ 利用記録の入室時刻よりも古い貸与日時を持つ貸し出し記録の内、最新1件のuserid」となると思います
つまり selec userid from m_secom_user where secom_id=t.secom_id and lending_dt <= t.reg_dt order by lending_dt desc limit 1 みたいなサブクエリをカラムとして追加すればよいと思います(試してないので細かいミスがあったらすみません)

投稿2023/09/04 05:19

pecmm

総合スコア760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

satou

2023/09/04 07:15

回答ありがとうございます。問題を整理していただき、また、考え方を学ぶことができたと思っています。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問