= Нормализација - TradingMK = == Де-нормализирана форма на базата == === Универзална релација === Тргнуваме од една единствена универзална релација која ги содржи сите атрибути од целиот домен на апликацијата — сите табели споени во еден единствен запис. Атрибутите се преименувани каде е потребно за да нема дупликати на имиња. {{{ Universal_Relation_TradingMK( user_id, username, password, email, role, auth_provider, portfolio_id, balance, holding_id, holding_quantity, avg_price, stock_id, stock_symbol, stock_name, current_price, last_price, percentage, turnover, last_updated, history_id, history_price, history_timestamp, trade_id, trade_type, trade_status, trade_quantity, price_per_unit, trade_timestamp, trade_stock_symbol, transaction_id, txn_type, txn_quantity, txn_price, txn_timestamp, txn_origin, watchlist_id, price_above, price_below, oauth_token, oauth_email, oauth_provider, oauth_expires_at, oauth_created_at ) }}} '''Напомени за именување:''' * trade_stock_symbol е преименуван (наспроти stock_symbol) за да избегне конфликт на имиња во универзалната релација * auth_provider е атрибут кој претставува вредност од user_auth_providers - повеќевредносен по природа * Нема дупликати на имиња на атрибути во универзалната релација === Функционални зависности === Ги идентификуваме сите функционални зависности кои важат глобално во универзалната релација. '''F = {''' * '''FD1:''' user_id → username, password, email, role * '''FD2:''' username → user_id * '''FD3:''' email → user_id * '''FD4:''' portfolio_id → balance, user_id * '''FD5:''' user_id → portfolio_id * '''FD6:''' stock_id → stock_symbol, stock_name, current_price, last_price, percentage, turnover, last_updated * '''FD7:''' stock_symbol → stock_id * '''FD8:''' holding_id → holding_quantity, avg_price, portfolio_id, stock_id * '''FD9:''' history_id → history_price, history_timestamp, stock_id * '''FD10:''' trade_id → trade_type, trade_status, trade_quantity, price_per_unit, trade_timestamp, trade_stock_symbol, portfolio_id * '''FD11:''' transaction_id → txn_type, txn_quantity, txn_price, txn_timestamp, txn_origin, user_id, stock_id * '''FD12:''' watchlist_id → price_above, price_below, user_id, stock_id * '''FD13:''' oauth_token → oauth_email, oauth_provider, oauth_expires_at, oauth_created_at, user_id '''}''' === Кандидат клучеви и примарен клуч === ==== Класификација на атрибути (Лева / Десна страна) ==== ||= Атрибут =||= Лева страна =||= Десна страна =||= Класификација =|| || user_id || ✓ (FD1, FD5) || ✓ (FD2, FD3, FD4, FD11, FD12, FD13) || и лево и десно || || username || ✓ (FD2) || ✓ (FD1) || и лево и десно || || password || ✗ || ✓ (FD1) || само десно || || email || ✓ (FD3) || ✓ (FD1) || и лево и десно || || role || ✗ || ✓ (FD1) || само десно || || auth_provider || ✗ || ✗ || '''само лево''' || || portfolio_id || ✓ (FD4) || ✓ (FD5, FD8, FD10) || и лево и десно || || balance || ✗ || ✓ (FD4) || само десно || || holding_id || ✓ (FD8) || ✗ || '''само лево''' || || holding_quantity || ✗ || ✓ (FD8) || само десно || || avg_price || ✗ || ✓ (FD8) || само десно || || stock_id || ✓ (FD6) || ✓ (FD7, FD8, FD9, FD11, FD12) || и лево и десно || || stock_symbol || ✓ (FD7) || ✓ (FD6) || и лево и десно || || stock_name || ✗ || ✓ (FD6) || само десно || || current_price || ✗ || ✓ (FD6) || само десно || || last_price || ✗ || ✓ (FD6) || само десно || || percentage || ✗ || ✓ (FD6) || само десно || || turnover || ✗ || ✓ (FD6) || само десно || || last_updated || ✗ || ✓ (FD6) || само десно || || history_id || ✓ (FD9) || ✗ || '''само лево''' || || history_price || ✗ || ✓ (FD9) || само десно || || history_timestamp || ✗ || ✓ (FD9) || само десно || || trade_id || ✓ (FD10) || ✗ || '''само лево''' || || trade_type || ✗ || ✓ (FD10) || само десно || || trade_status || ✗ || ✓ (FD10) || само десно || || trade_quantity || ✗ || ✓ (FD10) || само десно || || price_per_unit || ✗ || ✓ (FD10) || само десно || || trade_timestamp || ✗ || ✓ (FD10) || само десно || || trade_stock_symbol || ✗ || ✓ (FD10) || само десно || || transaction_id || ✓ (FD11) || ✗ || '''само лево''' || || txn_type || ✗ || ✓ (FD11) || само десно || || txn_quantity || ✗ || ✓ (FD11) || само десно || || txn_price || ✗ || ✓ (FD11) || само десно || || txn_timestamp || ✗ || ✓ (FD11) || само десно || || txn_origin || ✗ || ✓ (FD11) || само десно || || watchlist_id || ✓ (FD12) || ✗ || '''само лево''' || || price_above || ✗ || ✓ (FD12) || само десно || || price_below || ✗ || ✓ (FD12) || само десно || || oauth_token || ✓ (FD13) || ✗ || '''само лево''' || || oauth_email || ✗ || ✓ (FD13) || само десно || || oauth_provider || ✗ || ✓ (FD13) || само десно || || oauth_expires_at || ✗ || ✓ (FD13) || само десно || || oauth_created_at || ✗ || ✓ (FD13) || само десно || ==== Атрибути кои се појавуваат САМО на лева страна ==== Овие атрибути мора да бидат дел од секој кандидат клуч, бидејќи не можат да се изведат од ниедна FD: * '''holding_id''' - мора да биде дел од секој кандидат клуч * '''history_id''' - мора да биде дел од секој кандидат клуч * '''trade_id''' - мора да биде дел од секој кандидат клуч * '''transaction_id''' - мора да биде дел од секој кандидат клуч * '''watchlist_id''' - мора да биде дел од секој кандидат клуч * '''oauth_token''' - мора да биде дел од секој кандидат клуч * '''auth_provider''' - мора да биде дел од секој кандидат клуч (не учествува во ниедна FD; изводливо само преку себе) ==== Пресметка на затворач ==== ''Чекор 1:''' Започнуваме со задолжителни: {{{ {holding_id, history_id, trade_id, transaction_id, watchlist_id, oauth_token, auth_provider}: - Од FD8 (holding_id →): holding_quantity, avg_price, portfolio_id, stock_id - Од FD9 (history_id →): history_price, history_timestamp, stock_id - Од FD10 (trade_id →): trade_type, trade_status, trade_quantity, price_per_unit, trade_timestamp, trade_stock_symbol, portfolio_id - Од FD11 (transaction_id →): txn_type, txn_quantity, txn_price, txn_timestamp, txn_origin, user_id, stock_id - Од FD12 (watchlist_id →): price_above, price_below, user_id, stock_id - Од FD13 (oauth_token →): oauth_email, oauth_provider, oauth_expires_at, oauth_created_at, user_id - Од FD4 (portfolio_id →): balance, user_id - Од FD5 (user_id →): portfolio_id - Од FD1 (user_id →): username, password, email, role - Од FD6 (stock_id →): stock_symbol, stock_name, current_price, last_price, percentage, turnover, last_updated - Од FD7 (stock_symbol →): stock_id - Од FD2 (username →): user_id - Од FD3 (email →): user_id }}} {{{ {holding_id, history_id, trade_id, transaction_id, watchlist_id, oauth_token, auth_provider} = Universal_Relation_TradingMK ✓ (сите атрибути се изводливи) }}} ==== Проверка за минималност ==== ||= Подмножество (отстранет атрибут) =||= Недостасуваат атрибути =||= Суперклуч? =|| || без holding_id || holding_quantity, avg_price || ✗ НЕ || || без history_id || history_price, history_timestamp || ✗ НЕ || || без trade_id || trade_type, trade_status, trade_quantity, price_per_unit, trade_timestamp, trade_stock_symbol || ✗ НЕ || || без transaction_id || txn_type, txn_quantity, txn_price, txn_timestamp, txn_origin || ✗ НЕ || || без watchlist_id || price_above, price_below || ✗ НЕ || || без oauth_token || oauth_email, oauth_expires_at, oauth_created_at || ✗ НЕ || || без auth_provider || auth_provider не е изводливо || ✗ НЕ || Секој атрибут е неопходен - множеството е минимално. ==== Избор на примарен клуч ==== ''Кандидат клуч (и избран примарен клуч):''' {{{ PK = {holding_id, history_id, trade_id, transaction_id, watchlist_id, oauth_token, auth_provider} }}} '''Образложение:''' Примарниот клуч е голем бидејќи универзалната релација содржи повеќе независни ентитети (корисници, портфолија, акции, трговски барања, трансакции, watchlist записи, OAuth токени, auth провајдери) кои не се директно поврзани преку функционални зависности. Секој независен ентитет бара барем еден идентификатор во клучот. Клучот е минимален - отстранувањето на кој било атрибут го прави невозможно изведувањето на дел од атрибутите. ==== Нормална форма пред декомпозиција ==== Universal_Relation_TradingMK е во '''1NF''' (сите атрибути се атомарни, со исклучок на auth_provider кој е мулти-вредносен). Релацијата '''НЕ е во 2NF''' поради следните парцијални зависности - секој идентификатор ги определува само своите атрибути, независно од останатиот примарен клуч: * FD8: holding_id → holding_quantity, avg_price, portfolio_id, stock_id * FD9: history_id → history_price, history_timestamp, stock_id * FD10: trade_id → trade_type, trade_status, ..., portfolio_id * FD11: transaction_id → txn_type, ..., user_id, stock_id * FD12: watchlist_id → price_above, price_below, user_id, stock_id * FD13: oauth_token → oauth_email, oauth_provider, oauth_expires_at, oauth_created_at, user_id ---- == 1NF Декомпозиција == === Анализа === '''Анализирана релација:''' Universal_Relation_TradingMK '''Функционални зависности:''' FD1 - FD13 (сите) '''Кандидат клуч / Примарен клуч:''' {holding_id, history_id, trade_id, transaction_id, watchlist_id, oauth_token, auth_provider} '''Нормална форма:''' Релацијата е делумно во 1NF - атрибутот '''auth_provider''' претставува повеќевредносен (multi-valued) атрибут. Еден корисник може да има повеќе auth провајдери (интерен, Google), па оваа вредност не може да биде атомарна во унификованата релација. '''Зависност која го предизвикува проблемот:''' auth_provider е неделива повторувачка вредност поврзана со user_id - нема функционална зависност од единечен детерминант, туку претставува множество вредности. === Декомпозиција - Извлекување на auth_provider ===