Как построить схему данных для нескольких таблиц?

Как получить наглядное представление о связях нескольких таблиц, рассмотрим в статье.

Как показывает опыт, часто мы имеем большое количество таблиц в базах данных и крайне редко у них есть схема, по которой мы можем получить наглядное представление о связях всех таблиц. Когда у тебя две-три таблички, то схема не требуется, ее и так можно легко представить в голове. Но когда таблиц уже больше 10 или у них множество связей между друг другом, то это довольно проблематично сделать.

Конечно, эту схему можно нарисовать в специальной программе, но на это тоже требуется немалое количество времени.

Есть более быстрый вариант для рисования схемы данных таблиц! Мы будем использовать python и Graphviz.

1 этап: Заносим в Excel-файл названия таблиц и связи между ними.

Как построить схему данных для нескольких таблиц?

2 этап: Запускаем код на python:

from graphviz import Digraph import pandas as pd import random #считываем файл df = pd.read_excel("Связи.xlsx", dtype=str) #разносим таблицы и столбцы в два dataframe df1=df[["T1","S1"]] df2=df[["T2","S2"]] #для объединения переименуем столбцы df2=df2.rename(columns={'T2':'T1','S2':'S1'}) #объединяем два dataframe в один и убираем дубликаты df_concat=pd.concat([df1,df2]) df_concat=df_concat.drop_duplicates() df_concat.sort_values(by='T1') df_concat.reset_index(drop=True) #для создания node df_concat['T1_new']='['+df_concat['T1']+']' df_concat['S1_new']='|<'+df_concat['S1']+'> '+df_concat['S1'] df_concat=df_concat.drop(['T1','S1'], axis=1) df_concat['Count']=df_concat.groupby('T1_new').cumcount() df_pivot=df_concat.pivot('T1_new', 'Count', 'S1_new') df_p=pd.DataFrame(df_pivot.to_records()) df_p['concat']=pd.Series(df_p.fillna('').values.tolist()).str.join('') df_node_label=df_p[['T1_new','concat']] df_node_label['Res']=pd.Series(df_node_label.fillna('').values.tolist()).str.join('$#39;) #для связей df['Res']='['+df['T1']+']'+':'+df['S1']+'$#39;+'['+df['T2']+']'+':'+df['S2'] ar1=df_node_label['Res'].values ar2=df['Res'].values #отрисовка g=Digraph('structs',format='jpg') g.attr(rankdir="LR") g.attr('node', shape='record') g.attr(size='100') #рандомный цвет для ребер def rcolor(): r=random.randint(0,16777215) hexnumber=str(hex(r)) hexnumber='#'+hexnumber[2:] return hexnumber for i in ar1: node_ = i.split("$quot;)[0] node_label = i.split("$quot;)[1] g.node(node_,label=node_label) for i in ar2: edge1 = i.split("$quot;)[0] edge2 = i.split("$quot;)[1] #можно менять параметр minlen для изменения расстояния между nodes g.edge(edge1,edge2, color=rcolor(), minlen='5') g.view()

На выходе получаем готовую схему данных:

Как построить схему данных для нескольких таблиц?

Вот так быстро можно нарисовать схему данных, если мы уже знаем связи между таблицами.

7
Начать дискуссию
)\n#для связей\ndf['Res']='['+df['T1']+']'+':'+df['S1']+'$ +'['+df['T2']+']'+':'+df['S2']\nar1=df_node_label['Res'].values\nar2=df['Res'].values\n\n#отрисовка\ng=Digraph('structs',format='jpg')\ng.attr(rankdir=\"LR\")\ng.attr('node', shape='record')\ng.attr(size='100')\n\n#рандомный цвет для ребер\ndef rcolor():\n r=random.randint(0,16777215)\n hexnumber=str(hex(r))\n hexnumber='#'+hexnumber[2:]\n return hexnumber\n\nfor i in ar1:\n node_ = i.split(\"$$\")[0]\n node_label = i.split(\"$$\")[1]\n g.node(node_,label=node_label)\n \nfor i in ar2:\n edge1 = i.split(\"$$\")[0]\n edge2 = i.split(\"$$\")[1]\n #можно менять параметр minlen для изменения расстояния между nodes\n g.edge(edge1,edge2, color=rcolor(), minlen='5')\n\ng.view()","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

На выходе получаем готовую схему данных:

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"1186cf13-22db-5d91-bbee-7e081152494f","width":624,"height":768,"size":82545,"type":"png","color":"e0dfdf","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Вот так быстро можно нарисовать схему данных, если мы уже знаем связи между таблицами.

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":0,"favorites":13,"reposts":1,"views":4,"hits":1090,"reads":null,"online":0},"dateFavorite":0,"hitsCount":1090,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/dev/179879-kak-postroit-shemu-dannyh-dlya-neskolkih-tablic","author":{"id":447345,"name":"NTA","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"e7175678-aaab-09f8-0271-7b3af7ac4670","width":1207,"height":1207,"size":83090,"type":"jpg","color":"e3ebf8","hash":"","external_service":[]}},"cover":{"cover":{"type":"image","data":{"uuid":"8575b55d-a1f0-53ee-9ad6-78268f9ea45c","width":1280,"height":373,"size":56005,"type":"jpg","color":"b0b9ca","hash":"","external_service":[]}},"cover_y":0},"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4980908,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4980908"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1356821,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1356821"},{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":130113,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/130113"}],"lastModificationDate":1764953258,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":true,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":235819,"name":"Разработка","description":"Сообщество разработчиков: публикации о личном опыте, выдающиеся приёмы при решении рутинных задач, полезные материалы для профессионального роста.","uri":"/dev","avatar":{"type":"image","data":{"uuid":"fef5b5fb-e488-5b7f-8445-e3a26a910b44","width":1200,"height":1200,"size":7757,"type":"png","color":"343434","hash":"04042b2b1c1000","external_service":[]}},"cover":{"type":"image","data":{"uuid":"2a214cc5-35cc-58ca-bc07-fc1c892d2101","width":960,"height":280,"size":177,"type":"png","color":"343434","hash":"","external_service":[]}},"lastModificationDate":1642411346,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":false,"isDisabledAd":false,"nickname":"dev","isUnsubscribable":true,"badge":null,"badgeId":null,"isDonationsEnabled":false,"isOnline":false,"isPlus":false,"isUnverifiedBlogForCompanyWithoutPro":false,"isVerified":false,"isRemovedByUserRequest":false,"isFrozen":false,"isPro":false,"type":2,"subtype":"community"},"reactions":{"counters":[{"id":1,"count":7}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null,"keywords":["для","можно","объединяем","отрисовка","разносим","рандомный","считываем"],"media":null,"customCover":null,"robotsTag":"noindex","categories":[],"isAnonymized":true}};