简体   繁体   中英

Database Design - Multiple report types kept in one table or multiple tables

I have read the answers to the following questions and I believe they point to two different answers:

Database Design: Multiple tables vs a single table

MySQL Question - How to handle multiple types of users - one table or multiple?

My database: MySQL My language: PHP My problem: I have 4 reports to keep in a database (possibly more in the future). Each report has different inputs than the other. I created a different module for each. I was trying to use Object-oriented design by creating one table to store the common columns (createddate, createdby, reportnumber, title, etc). However I am ending up with a lot of code that identifies what tables to go look at depending on the report being used as well as other parameters. Basically it seems to be getting bigger than if I had used the much of the same code in each module with the exact tables and column names needed for that report. And of course, I'm running into at least 2 columns that are needed in this combined table that will have NULL values for some reports and not others.

The one answer in the above links says to create many tables (many to many) while the other says to have 1 common table with multiple specific tables for the specific users (reports in my case).

Unless I misunderstood what I was reading, which may very well be the case.

My question: Should I create individual tables for each report and have similar queries and table setups in the code OR create a main common table for all reports and have code that queries the db and lays out the tables but needs to either have many variables passed in or have the ability to look up the needed table/column/paths/heading information?

EDIT 2: Sorry for the confusion

Here's what I first had

database tables

abc_reports: abc_id, site, system, country, reportnumber, title, createddate, statusid (no duedate)
abc_details: abcdetails_id, abc_id, abc_date, abc_time, location, description, actions
abc_qa: abcqa_id, abc_id, near_miss, opp_improv, level

def_reports: def_id, country, reportnumber, title, createddate, duedate, statusid (no site/sytem, but added duedate)
def_details: defdetails_id, def_id, jobnumber, type, partnumber, part_descrip, serial_num
def_qa: defqa_id, def_id, major, disposition, rep_required, dispo_descrip, dispo_date

xyz_reports: xyz_id, site, system, country, reportnumber, title, createddate (no statusid or duedate)
xyz_details: xyzdetails_id, xyz_id, customer, workgroup, contract_num

Webpage layout: ABC Reports: Description of report, form to add a new ABC report, summary table (html) showing the last few reports with the column headers of Created Date, Created By, Report Number, Title, Status, Country, and Site

DEF Reports: Description of report, form to add a new DEF report, summary table (html) showing the last few reports with the column headers of Created Date, Created By, Report Number, Title, Status, Due Date, and Country

XYZ Reports: Description of report, form to add a new XYZ report, summary table (html) showing the last few reports with the column headers of Created Date, Created By, Report Number, Title, Country, and Site

The SQL queries and the html-table layouts would be tailored specifically for each of those reports.

Seeing that I would be using very similar queries and displaying very similar tables, I opted to remove the "_reports" tables and replace with one table "reports" So now the tables are like this:

reports: report_id(auto-increment), site, system, country, reportnumber, title, createddate, etc
reportstatus: report_id(inserted after new report on reports table), statusid, assignedto, duedate, reviewed, declined, etc

abc_details: abcdetails_id, abc_id, abc_date, abc_time, location, description, actions
abc_qa: abcqa_id, abc_id, near_miss, opp_improv, level

def_details: defdetails_id, def_id, jobnumber, type, partnumber, part_descrip, serial_num
def_qa: defqa_id, def_id, major, disposition, rep_required, dispo_descrip, dispo_date

xyz_details: xyzdetails_id, xyz_id, customer, workgroup, contract_num

Now the Webpage layout needs to search out the reports table for the summary info, but now has to look for a report number with a prefix that matches whichever module the user is looking at. So I created a function that returns an array of variables for each type of report (Boolean for 'use_due_date' in an SQL query, Boolean for 'use_status_id', path to this particular report's details webpage, the Report Name (ABC, or DEF, etc), SQL Joining statement for its specific tables, etc. This function is called by the now common summary table whenever a reports module is viewed by a user.

Here's a sample:

$sSQL  = "SELECT ";
$sSQL .= "r.reportid, ";
$sSQL .= "r.reportnumber, ";
$sSQL .= "r.title, ";
if ($arrModValues["siteused"]) { $sSQL .= "r.siteid, "; }
$sSQL .= "r.createddate, ";
$sSQL .= "rs.statusid, ";
if ($arrModValues["duedateused"]) {
    $sSQL .= "rs.duedate, ";
    $sSQL .= "rs.duedate < CURDATE() AS is_pastdue, ";
    $sSQL .= "rs.duedate <= CURDATE() + 7 AS is_almostdue, ";
}

$sSQL .= "rs.reviewed, ";
$sSQL .= "rs.declined, "
$sSQL .= "rs.finalized, ";
$sSQL .= "r.createdby, ";
$sSQL .= "rs.assignedto ";
$sSQL .= "FROM reports r ";
$sSQL .= "LEFT JOIN reportstatus rs ON r.reportid = rs.reportid "
$sSQL .= get_joining_statement($sMod);
$sSQL .= "WHERE ";
$sSQL .= "moduleid = '$sMod' AND ";
$sSQL .= "countryid='$sCountry' ";
$sSQL .= "ORDER BY ";
$sSQL .= "createddate ";

$sSQL .= "DESC";


// get the query results

$arrResults = query($sSQL);

Then the common table:
if ($arrResults) {

// get headers for header table

$arrHeaderDef = array();

$arrHeaderDef[]     = "Created";
$arrHeaderDef[]     = "Report Number";
$arrHeaderDef[]     = "Title";
if ($arrModValues["siteused"]) { $arrHeaderDef[] = "Site"; }
$arrHeaderDef[]     = "Status";
if ($arrModValues["duedateused"]) { $arrHeaderDef[] = "Due Date"; }

$arrHeaderDef[]     = "Disposition";
$arrHeaderDef[]     = "Created By";
$arrHeaderDef[]     = "Assigned To";
$arrHeaderDef[]     = $arrModValues["coltitle"];
$arrTable[] = $arrHeaderDef;

and so on...

I hope this hasn't made my question more convoluted. If you wish to point out any programming design mistakes, feel free.

So the big question is: should I have left the original tables alone and created similar but specific PHP/SQL code for each module (report) like the answer suggests in the first link above OR was I on the right path by trying to combine the common elements of the reports and create common queries and table layouts like the answer to the 2nd link above suggests? Or neither? What would be the better way to design this system?

Thank you again. Sorry it is so long and discombobulated.

Thank you, Sam

How many reports are you planning to get?

I once had the same problem and solved it by adding a really big table with all the columns that could possible show up. A lot of columns would get empty depending on event, but query one table at a time is much less headache. But to make it scalable I ended up creating automatically a new table per month using a reference table as the most queried data would be from the current month anyways.

reftable
id, sekid, table (table would refer to which table below)

table201401
sekid,column,column,etc,etc,etc

table201402
sekid,column,column,etc,etc,etc

That would make every column easy to search and so on after setting the month to query. But depending on your data is to be used with, like if it's gonna be searchable and sortable and so on. A lot of data you might get away with storing as json strings. Is like storing an array with values in a single column. Not very searchable and sortable, but saves a lot of space if it's something you just need to print out as a reference.

As in my case the main reason I ended up doing what I did was just that the data manipulation would be extreme for the current month. Next month the last month table would only be used as references and occasionally updated.

Every case has it's spcific needs to take in concern and is always good to think big and scalable. Find the balance of what is managable and acceptable. I hope this post give you some pointers. I thought I would share it as I remember myself once asking the very same question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM