Add show_checkin_data_sql.py
This commit is contained in:
248
show_checkin_data_sql.py
Normal file
248
show_checkin_data_sql.py
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
SQL直接実行版: 最近のGpsLogとCheckinImagesデータを表示
|
||||||
|
Docker環境で動作
|
||||||
|
"""
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
def run_db_query(query):
|
||||||
|
"""
|
||||||
|
PostgreSQLクエリを実行
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
cmd = [
|
||||||
|
'docker-compose', 'exec', '-T', 'db',
|
||||||
|
'psql', '-U', 'admin', '-d', 'rogdb',
|
||||||
|
'-c', query
|
||||||
|
]
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
cmd,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
cwd='/Volumes/PortableSSD1TB/main/GifuTabi/rogaining_srv_exdb-2/rogaining_srv'
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode == 0:
|
||||||
|
return result.stdout
|
||||||
|
else:
|
||||||
|
print(f"❌ SQLエラー: {result.stderr}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 実行エラー: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def show_recent_gpslog(days=7):
|
||||||
|
"""
|
||||||
|
最近のGpsLogデータを表示
|
||||||
|
"""
|
||||||
|
print(f"\n📍 GpsLog (過去{days}日間)")
|
||||||
|
print("-" * 80)
|
||||||
|
|
||||||
|
query = f"""
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
to_char(checkin_time, 'MM-DD HH24:MI:SS') as time,
|
||||||
|
zekken_number,
|
||||||
|
event_code,
|
||||||
|
cp_number,
|
||||||
|
CASE
|
||||||
|
WHEN image_address IS NOT NULL AND image_address != '' THEN '✅'
|
||||||
|
ELSE '❌'
|
||||||
|
END as has_image,
|
||||||
|
CASE
|
||||||
|
WHEN length(image_address) > 50 THEN left(image_address, 47) || '...'
|
||||||
|
ELSE coalesce(image_address, '')
|
||||||
|
END as image_preview
|
||||||
|
FROM rog_gpslog
|
||||||
|
WHERE checkin_time >= NOW() - INTERVAL '{days} days'
|
||||||
|
ORDER BY checkin_time DESC
|
||||||
|
LIMIT 20;
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = run_db_query(query)
|
||||||
|
if result:
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
def show_recent_checkinimages(days=7):
|
||||||
|
"""
|
||||||
|
最近のCheckinImagesデータを表示
|
||||||
|
"""
|
||||||
|
print(f"\n🖼️ CheckinImages (過去{days}日間)")
|
||||||
|
print("-" * 80)
|
||||||
|
|
||||||
|
query = f"""
|
||||||
|
SELECT
|
||||||
|
ci.id,
|
||||||
|
to_char(ci.checkintime, 'MM-DD HH24:MI:SS') as time,
|
||||||
|
left(cu.email, 15) as user_email,
|
||||||
|
left(ci.team_name, 12) as team,
|
||||||
|
left(ci.event_code, 10) as event,
|
||||||
|
ci.cp_number,
|
||||||
|
CASE
|
||||||
|
WHEN ci.checkinimage IS NOT NULL AND ci.checkinimage != '' THEN '✅'
|
||||||
|
ELSE '❌'
|
||||||
|
END as has_file,
|
||||||
|
CASE
|
||||||
|
WHEN length(ci.checkinimage::text) > 30 THEN left(ci.checkinimage::text, 27) || '...'
|
||||||
|
ELSE coalesce(ci.checkinimage::text, '')
|
||||||
|
END as file_preview
|
||||||
|
FROM rog_checkinimages ci
|
||||||
|
LEFT JOIN auth_user cu ON ci.user_id = cu.id
|
||||||
|
WHERE ci.checkintime >= NOW() - INTERVAL '{days} days'
|
||||||
|
ORDER BY ci.checkintime DESC
|
||||||
|
LIMIT 20;
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = run_db_query(query)
|
||||||
|
if result:
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
def show_table_stats():
|
||||||
|
"""
|
||||||
|
テーブル統計情報を表示
|
||||||
|
"""
|
||||||
|
print(f"\n📊 テーブル統計")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
query = """
|
||||||
|
SELECT
|
||||||
|
'GpsLog' as table_name,
|
||||||
|
count(*) as total_count,
|
||||||
|
count(CASE WHEN image_address IS NOT NULL AND image_address != '' THEN 1 END) as with_image,
|
||||||
|
to_char(min(checkin_time), 'YYYY-MM-DD') as oldest_date,
|
||||||
|
to_char(max(checkin_time), 'YYYY-MM-DD HH24:MI') as latest_date
|
||||||
|
FROM rog_gpslog
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
'CheckinImages' as table_name,
|
||||||
|
count(*) as total_count,
|
||||||
|
count(CASE WHEN checkinimage IS NOT NULL AND checkinimage != '' THEN 1 END) as with_file,
|
||||||
|
to_char(min(checkintime), 'YYYY-MM-DD') as oldest_date,
|
||||||
|
to_char(max(checkintime), 'YYYY-MM-DD HH24:MI') as latest_date
|
||||||
|
FROM rog_checkinimages;
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = run_db_query(query)
|
||||||
|
if result:
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
def show_event_stats():
|
||||||
|
"""
|
||||||
|
イベント別統計を表示
|
||||||
|
"""
|
||||||
|
print(f"\n🎯 イベント別統計 (GpsLog)")
|
||||||
|
print("-" * 40)
|
||||||
|
|
||||||
|
query = """
|
||||||
|
SELECT
|
||||||
|
event_code,
|
||||||
|
count(*) as checkin_count,
|
||||||
|
count(CASE WHEN image_address IS NOT NULL AND image_address != '' THEN 1 END) as with_image_count,
|
||||||
|
to_char(min(checkin_time), 'MM-DD') as first_checkin,
|
||||||
|
to_char(max(checkin_time), 'MM-DD') as last_checkin
|
||||||
|
FROM rog_gpslog
|
||||||
|
GROUP BY event_code
|
||||||
|
ORDER BY checkin_count DESC
|
||||||
|
LIMIT 10;
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = run_db_query(query)
|
||||||
|
if result:
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
print(f"\n🖼️ イベント別統計 (CheckinImages)")
|
||||||
|
print("-" * 40)
|
||||||
|
|
||||||
|
query = """
|
||||||
|
SELECT
|
||||||
|
event_code,
|
||||||
|
count(*) as image_count,
|
||||||
|
count(DISTINCT team_name) as unique_teams,
|
||||||
|
to_char(min(checkintime), 'MM-DD') as first_image,
|
||||||
|
to_char(max(checkintime), 'MM-DD') as last_image
|
||||||
|
FROM rog_checkinimages
|
||||||
|
GROUP BY event_code
|
||||||
|
ORDER BY image_count DESC
|
||||||
|
LIMIT 10;
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = run_db_query(query)
|
||||||
|
if result:
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
def show_recent_activity():
|
||||||
|
"""
|
||||||
|
最近のアクティビティを時系列で表示
|
||||||
|
"""
|
||||||
|
print(f"\n⏰ 最近のアクティビティ (時系列)")
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
query = """
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
'GpsLog' as source,
|
||||||
|
checkin_time as timestamp,
|
||||||
|
zekken_number as identifier,
|
||||||
|
event_code,
|
||||||
|
cp_number,
|
||||||
|
CASE WHEN image_address IS NOT NULL AND image_address != '' THEN 'with_image' ELSE 'no_image' END as note
|
||||||
|
FROM rog_gpslog
|
||||||
|
WHERE checkin_time >= NOW() - INTERVAL '24 hours'
|
||||||
|
)
|
||||||
|
UNION ALL
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
'CheckinImages' as source,
|
||||||
|
checkintime as timestamp,
|
||||||
|
team_name as identifier,
|
||||||
|
event_code,
|
||||||
|
cp_number::text,
|
||||||
|
'image_upload' as note
|
||||||
|
FROM rog_checkinimages
|
||||||
|
WHERE checkintime >= NOW() - INTERVAL '24 hours'
|
||||||
|
)
|
||||||
|
ORDER BY timestamp DESC
|
||||||
|
LIMIT 15;
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = run_db_query(query)
|
||||||
|
if result:
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
メイン関数
|
||||||
|
"""
|
||||||
|
print("🏃♂️ ロゲイニング チェックインデータ表示ツール (SQL版)")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
# 引数処理
|
||||||
|
days = 7
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
try:
|
||||||
|
days = int(sys.argv[1])
|
||||||
|
except ValueError:
|
||||||
|
print("⚠️ 日数は数値で指定してください (デフォルト: 7日)")
|
||||||
|
days = 7
|
||||||
|
|
||||||
|
print(f"📅 過去{days}日間のデータを表示します")
|
||||||
|
|
||||||
|
# データ表示
|
||||||
|
show_recent_gpslog(days)
|
||||||
|
show_recent_checkinimages(days)
|
||||||
|
show_table_stats()
|
||||||
|
show_event_stats()
|
||||||
|
show_recent_activity()
|
||||||
|
|
||||||
|
print(f"\n✅ 完了")
|
||||||
|
print(f"\n使用方法: python3 {sys.argv[0]} [日数]")
|
||||||
|
print(f"例: python3 {sys.argv[0]} 3 # 過去3日間のデータ")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
175
show_recent_checkin_data.py
Normal file
175
show_recent_checkin_data.py
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
最近のGpsLogとCheckinImagesデータを表示するスクリプト
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import django
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
# Django設定
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
from rog.models import GpsLog, CheckinImages, CustomUser
|
||||||
|
from django.db import connection
|
||||||
|
|
||||||
|
def show_recent_data(days=7):
|
||||||
|
"""
|
||||||
|
最近のチェックインデータを表示
|
||||||
|
|
||||||
|
Args:
|
||||||
|
days (int): 過去何日分のデータを表示するか
|
||||||
|
"""
|
||||||
|
# 基準日時を計算
|
||||||
|
since_date = timezone.now() - timedelta(days=days)
|
||||||
|
|
||||||
|
print(f"=== 過去{days}日間のチェックインデータ ===")
|
||||||
|
print(f"検索期間: {since_date.strftime('%Y-%m-%d %H:%M:%S')} 以降")
|
||||||
|
print("-" * 80)
|
||||||
|
|
||||||
|
# GpsLogの最近のデータ
|
||||||
|
print("\n📍 GpsLog (チェックイン記録)")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
recent_gpslogs = GpsLog.objects.filter(
|
||||||
|
checkin_time__gte=since_date
|
||||||
|
).order_by('-checkin_time')[:20]
|
||||||
|
|
||||||
|
if recent_gpslogs:
|
||||||
|
print(f"件数: {recent_gpslogs.count()}件")
|
||||||
|
print()
|
||||||
|
print("ID | 時刻 | ゼッケン | イベント | CP | 画像URL")
|
||||||
|
print("-" * 80)
|
||||||
|
|
||||||
|
for log in recent_gpslogs:
|
||||||
|
image_status = "✅" if log.image_address else "❌"
|
||||||
|
image_url_preview = log.image_address[:40] + "..." if log.image_address and len(log.image_address) > 40 else log.image_address or ""
|
||||||
|
|
||||||
|
print(f"{log.id:5d} | {log.checkin_time.strftime('%m-%d %H:%M:%S'):15s} | {log.zekken_number:8s} | {log.event_code:11s} | {log.cp_number:4s} | {image_status} {image_url_preview}")
|
||||||
|
else:
|
||||||
|
print("データなし")
|
||||||
|
|
||||||
|
# CheckinImagesの最近のデータ
|
||||||
|
print(f"\n🖼️ CheckinImages (写真記録)")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
recent_images = CheckinImages.objects.filter(
|
||||||
|
checkintime__gte=since_date
|
||||||
|
).order_by('-checkintime')[:20]
|
||||||
|
|
||||||
|
if recent_images:
|
||||||
|
print(f"件数: {recent_images.count()}件")
|
||||||
|
print()
|
||||||
|
print("ID | 時刻 | ユーザー | チーム名 | イベント | CP | 画像ファイル")
|
||||||
|
print("-" * 100)
|
||||||
|
|
||||||
|
for img in recent_images:
|
||||||
|
user_name = img.user.email[:12] if img.user else "Unknown"
|
||||||
|
team_name = img.team_name[:12] if img.team_name else ""
|
||||||
|
event_code = img.event_code[:11] if img.event_code else ""
|
||||||
|
image_file = str(img.checkinimage)[:30] + "..." if len(str(img.checkinimage)) > 30 else str(img.checkinimage)
|
||||||
|
|
||||||
|
print(f"{img.id:5d} | {img.checkintime.strftime('%m-%d %H:%M:%S'):15s} | {user_name:12s} | {team_name:12s} | {event_code:11s} | {img.cp_number:4d} | {image_file}")
|
||||||
|
else:
|
||||||
|
print("データなし")
|
||||||
|
|
||||||
|
def show_summary_stats():
|
||||||
|
"""
|
||||||
|
チェックインデータの統計情報を表示
|
||||||
|
"""
|
||||||
|
print(f"\n📊 データベース統計")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
# 各テーブルの総件数
|
||||||
|
gpslog_total = GpsLog.objects.count()
|
||||||
|
checkinimages_total = CheckinImages.objects.count()
|
||||||
|
|
||||||
|
print(f"GpsLog 総件数: {gpslog_total:,}")
|
||||||
|
print(f"CheckinImages 総件数: {checkinimages_total:,}")
|
||||||
|
|
||||||
|
# 最新・最古のデータ
|
||||||
|
if gpslog_total > 0:
|
||||||
|
latest_gpslog = GpsLog.objects.order_by('-checkin_time').first()
|
||||||
|
oldest_gpslog = GpsLog.objects.order_by('checkin_time').first()
|
||||||
|
print(f"GpsLog 最新: {latest_gpslog.checkin_time.strftime('%Y-%m-%d %H:%M:%S') if latest_gpslog else 'N/A'}")
|
||||||
|
print(f"GpsLog 最古: {oldest_gpslog.checkin_time.strftime('%Y-%m-%d %H:%M:%S') if oldest_gpslog else 'N/A'}")
|
||||||
|
|
||||||
|
if checkinimages_total > 0:
|
||||||
|
latest_image = CheckinImages.objects.order_by('-checkintime').first()
|
||||||
|
oldest_image = CheckinImages.objects.order_by('checkintime').first()
|
||||||
|
print(f"CheckinImages 最新: {latest_image.checkintime.strftime('%Y-%m-%d %H:%M:%S') if latest_image else 'N/A'}")
|
||||||
|
print(f"CheckinImages 最古: {oldest_image.checkintime.strftime('%Y-%m-%d %H:%M:%S') if oldest_image else 'N/A'}")
|
||||||
|
|
||||||
|
# 画像有りのGpsLog件数
|
||||||
|
gpslog_with_images = GpsLog.objects.exclude(image_address__isnull=True).exclude(image_address='').count()
|
||||||
|
print(f"画像付きGpsLog: {gpslog_with_images:,} / {gpslog_total:,} ({gpslog_with_images/gpslog_total*100:.1f}%)" if gpslog_total > 0 else "画像付きGpsLog: 0")
|
||||||
|
|
||||||
|
def show_event_breakdown():
|
||||||
|
"""
|
||||||
|
イベント別のチェックイン件数を表示
|
||||||
|
"""
|
||||||
|
print(f"\n🎯 イベント別チェックイン件数")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
# GpsLogのイベント別集計
|
||||||
|
print("GpsLog:")
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT event_code, COUNT(*) as count
|
||||||
|
FROM rog_gpslog
|
||||||
|
GROUP BY event_code
|
||||||
|
ORDER BY count DESC
|
||||||
|
LIMIT 10
|
||||||
|
""")
|
||||||
|
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
print(f" {row[0]:15s}: {row[1]:,}件")
|
||||||
|
|
||||||
|
# CheckinImagesのイベント別集計
|
||||||
|
print("\nCheckinImages:")
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT event_code, COUNT(*) as count
|
||||||
|
FROM rog_checkinimages
|
||||||
|
GROUP BY event_code
|
||||||
|
ORDER BY count DESC
|
||||||
|
LIMIT 10
|
||||||
|
""")
|
||||||
|
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
print(f" {row[0]:15s}: {row[1]:,}件")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
メイン関数
|
||||||
|
"""
|
||||||
|
print("🏃♂️ ロゲイニング チェックインデータ表示ツール")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 引数処理
|
||||||
|
days = 7
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
try:
|
||||||
|
days = int(sys.argv[1])
|
||||||
|
except ValueError:
|
||||||
|
print("⚠️ 日数は数値で指定してください")
|
||||||
|
days = 7
|
||||||
|
|
||||||
|
# データ表示
|
||||||
|
show_recent_data(days)
|
||||||
|
show_summary_stats()
|
||||||
|
show_event_breakdown()
|
||||||
|
|
||||||
|
print(f"\n✅ 完了")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ エラーが発生しました: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user