Mysql
 sql >> база данни >  >> RDS >> Mysql

Бази данни:Създаване на дневник на действията, как да се справят с различни препратки?

По-долу е как бих го направил. Имам още няколко коментара в долната част, след като сте видели схемата.

Регистър

LogID - уникален идентификационен номер на дневника

Час - дата/час на събитието

LogType - низ или ID

(страничен коментар, бих отишъл с идентификатор тук, за да можете да използвате таблица със съобщения, показана по-долу, но ако искате бързо n мръсно, можете просто уникален низ за всеки лог време (напр. "Играта започна", "Изпратено съобщение" и др.)

LogActor

LogID - външен ключ

LogActorType - низ или идентификатор (както по-горе, ако идентификаторът ще ви е необходима таблица за справка)

LogActorID – Това е уникален идентификатор на таблицата за типа напр. потребител, група, игра

Последователност - това е подреждане на актьорите.

LogMessage

LogType - външен ключ

Съобщение - дълъг низ (varchar(max)?)

Език - низ (5), за да можете да изключите различен език, напр. "US-en"

Примерни данни (като използвате вашите 3 примера)

Регистър

ID  Time   LogType 
1   1/1/10 1
2   1/1/10 2
3   1/1/10 3

LogActor

LogID LogActorType LogActorID Sequence
1     User         1          1
1     User         2          2
2     User         1          1
2     User         2          2
2     User         2          3
2     Game         1          4
3     User         3          1
3     Group        1          2

LogMessage

LogType Message 
1       {0} Made a new friend {1}
2       {0}, {1}, {2} played a game ({3})
3       {0} joined a group ({1})

Потребител

ID Name
1  User A
2  User B
3  User C

Игра

ID Name
1  Name of game

Група

ID Name
1  Name of group

Ето хубавите неща за този дизайн.

  • Много е лесно да се разшири

  • Той се занимава с многоезични проблеми, независимо от актьорите

  • Тя се самодокументира, таблицата LogMessage обяснява какво точно трябва да казват данните, които съхранявате.

Някои лоши неща за това.

  • Трябва да извършите сложна обработка, за да прочетете съобщенията.

  • Не можете просто да погледнете DB и да видите какво се е случило.

Според моя опит добрите части на този вид дизайн надвишават лошите. Това, което направих, за да ми позволя да направя бърз n мръсен преглед на дневника, е да направя изглед (който не използвам за кода на приложението), който мога да гледам, когато трябва да видя какво се случва отзад край.

Кажете ми, ако имате въпроси.

Актуализация – Някои примерни заявки

Всички мои примери са в sqlserver 2005+, уведомете ме, ако има различна версия, към която искате да насочвам.

Вижте таблицата LogActor (Има няколко начина да направите това, най-доброто зависи от много неща, включително разпространение на данни, случаи на използване и т.н.) Ето два:

а)

SELECT 
  LogId,
  COLLESCE(U.Name,Ga.Name,Go.Name) AS Name,
  Sequence
FROM LogActor A
LEFT JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
LEFT JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
LEFT JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
ORDER BY LogID, Sequence

б)

SELECT 
  LogId,
  U.Name AS Name,
  Sequence
FROM LogActor A
INNER JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
UNION ALL
SELECT 
  LogId,
  Ga.Name AS Name,
  Sequence
FROM LogActor A
INNER JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
UNION ALL
SELECT 
  LogId,
  Go.Name AS Name,
  Sequence
FROM LogActor A
INNER JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
ORDER BY LogID, Sequence

Като цяло мисля, че а) е по-добре от б) Например, ако ви липсва актьор, тип а) ще го включи (с нулево име). Въпреки това b) е по-лесен за поддръжка (защото операторите UNION ALL го правят по-модулен.) Има и други начини да направите това (напр. CTE, изгледи и т.н.). Склонен съм да го направя като б) и от това, което видях, това изглежда поне стандартна практика, ако не и най-добра практика.

И така, последните 10 елемента в регистрационния файл ще изглеждат по следния начин:

SELECT 
  LogId,
  M.Message,
  COLLESCE(U.Name,Ga.Name,Go.Name) AS Name,
  Time,
  A.Sequence
FROM Log
LEFT JOIN LogActor A ON Log.LogID = A.LogID
LEFT JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
LEFT JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
LEFT JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
LEFT JOIN LogMessage M ON Log.LogType = M.LogMessage
WHERE LogID IN (SELECT Top 10 LogID FROM Log ORDER BY Date DESC)
ORDER BY Date, LogID, A.Sequence

NB – Както можете да видите, по-лесно е да изберете всички елементи от дневника от дадена дата, отколкото последния X, защото за това се нуждаем от (вероятно много бърза) подзаявка.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL my.ini местоположение

  2. SQLAlchemy ПРИ АКТУАЛИЗИРАНЕ НА ДУБЛИРАН КЛЮЧ

  3. Как да получите възраст от D.O.B поле в MySQL?

  4. Left Join превъзхожда Inner Join?

  5. Как да форматирате низове на SQL IN клауза с Python