优化已有重复条目的表

时间:2014-10-26 21:46:11

标签: php mysql sql database

目前我的原始数据格式如下

             ---------------------------------------------------------------------
            | User           Number           charges        cost     account#   |
            | John Smith    555-555-5555      Rental         $700      12345     |
            | John Smith    555-555-5555      Phone          $100      12345     |
            | Mike Jones    444-444-4444      Late Pay       $50       98765     |
            | John Smith    555-555-5555      Surcharge      $100      12345     |
            ----------------------------------------------------------------------

这只是我把它放在一起的一个例子,但是在原始数据没有适当分组的方面,设置几乎相同。正如您可以看到细分列表John Smith及其信息,然后跳转到Mike Jones,然后回到John Smith,在usernumberaccount#中创建了许多重复的条目柱。我拥有的真实数据文件是以这种方式设置的,但由数千行和10-20列组成。我一直试图找到一种方法来打破用户名和数字到一个单独的表中,我可以在其中创建与文件其余部分的关系,以帮助优化表。我意识到如果我手动输入每个条目,我就可以这样做,但这显然会占用很多时间,并且每次需要将其中一个数据文件上传到数据库时,这是不可行的。

最初我以为我只会创建一个用户名表来保存用户的名称和号码,对于每个用户,我会有一个自动递增的键,它将链接到表的其余部分。我遇到的问题是,对于像John Smith这样的人,我会有一个看起来像这样的表:

               --------------------------------------
              | ID        User       Number         |
              | 1        John Smith  555-555-5555   |
              | 2        Mike Jones  444-444-4444   |
              ---------------------------------------

我必须进入并在主表中为其名称的每个实例输入1的外键:

             -----------------------------------------------------
            | ID        Charges        Cost          account#    |
            | 1         Rental         $700          12345       |
            | 1         Phone          $100          12345       | 
            | 2         Late Pay       $50           98765       |
            | 1         Surcharge      $100          12345       |
           --------------------------------------------------------

有没有办法在没有进入的情况下连接表格,并且每次收费表都有与约翰史密斯有关的东西时手动输入1

2 个答案:

答案 0 :(得分:1)

您可以使用第三个表作为两者之间的链接。

使用你的例子,我考虑做类似的事情:

USER_TABLE

   -----------------------------------------
  |    User       Number         acccount# |
  |   John Smith  555-555-5555   12345     |
  |   Mike Jones  444-444-4444   98765     |
  ------------------------------------------

order_table

     ------------------------------------------
    | Order#        Charges        Cost       |
    | 1             Rental         $700       |
    | 2             Phone          $100       | 
    | 3             Late Pay       $50        |
    | 4             Surcharge      $100       |
     ------------------------------------------

user_orders_table

     ----------------------------
    | account#        order#    |
    | 12345               1     |
    | 12345               2     | 
    | 98765               3     |
    | 12345               4     |
     ----------------------------

订单#将由您的数据库自动递增。假设帐号是设计上唯一的,因此它可以作为user_table的主键。然后user_orders_table将是存储两个表之间链接的方法。

<强>更新

如果需要保留用户表的数据库管理标识符,则可以按如下方式调整示例:

USER_TABLE

   -------------------------------------------------
  | user_uid   User       Number         acccount# |
  | 1          John Smith  555-555-5555   12345    |
  | 2          Mike Jones  444-444-4444   98765    |
  --------------------------------------------------

order_table

     ------------------------------------------
    | Order#        Charges        Cost       |
    | 1             Rental         $700       |
    | 2             Phone          $100       | 
    | 3             Late Pay       $50        |
    | 4             Surcharge      $100       |
     ------------------------------------------

user_orders_table

     ----------------------------
    | user_id         order#    |
    | 1               1         |
    | 1               2         | 
    | 2               3         |
    | 1               4         |
     ----------------------------

更新2

实现此目的的一种方法是使用procedure进行插入。使用存储过程的目标是实现注释中提到的步骤。

插入新订单

1.  Check for user

   1.a  User exists, get their id

   1.b  User does not exits.  Insert them and get their id.

2.  Create new order record

3.  Create user_orders record

请将此视为伪代码。

我无法访问MySQL数据库来测试这个......而且它只是想提供一个更详细的理论示例来说明如何实现。

DELIMITER //
CREATE PROCEDURE InsertOrder(
    IN 
        p_user_name VARCHAR(50), 
        p_user_phone_number VARCHAR(13), 
        p_user_account_number VARCHAR(50),
        p_order_charges VARCHAR(15), 
        p_order_cost MEDINT
)
 BEGIN
    //check for the user in the database. If they exist, get their id.  If they don't, insert them
    IF EXISTS (SELECT user_uid FROM USERS_TABLE WHERE user_name = p_user_name) //user exists... get their uid
        r_user_uid = user_uid;
    ELSE  //user doesn't exist... create the sucker
        INSERT INTO USER_TABLE (user_name, user_phone_number, user_account_number) 
                    VAULES(p_user_name, p_user_phone_number, p_user_account_number); //assuming that user_uid is an auto_incremented value
        r_user_uid = SELECT user_uid FROM USERS_TABLE WHERE user_name = p_user_name;
    END IF
    //insert your order information NOTE:  could be prudent to check if the order exists already... but we will assume it doesn't for the sake of the pseudo code example.
    INSERT INTO ORDER_TABLE (order_charges, order_cost) 
        VALUES (p_order_charges, p_order_cost); --assuming that order number is an auto_incremented value.
        r_order_id = SELECT max(order_number) FROM ORDER_TABLE //assumes the latest entry is the correct one... may not be the most robust way to do this... depending on how this is to be used overall.
    //Now create the user_orders record
    INSERT INTO USER_ORDERS_TABLE (user_id, order_number) VALUES (r_user_uid, r_order_number);
 END //
DELIMITER ;

请注意: 在其他评论中,在原始问题之后,您提到数据集中的用户没有真正的唯一数据。对于您来说,这对于实现这样的解决方案来说可能是一个真正的问题。要拥有一个良好的用户表,您需要一种方法使数据本身是唯一的。仅依靠数据库生成的标识符并不理想......不推荐使用。例如,如果要输入

User      Number             account#
John Doe  555-555-5555       12345
John Doe  555-444-3333       12345
John Doe  555-555-5555       12345

这是两个具有相同名称的不同用户的列表;或者是同一个用户,他们的电话号码是谁?为了创建一个良好的用户表,您必须能够从要插入的数据中确定这一点。因此,需要一些额外的部分来唯一地识别用户。

您可能在剩余的列中包含其他数据,以帮助您完成此任务...但如果不是......那么创建用户表可能不是规范化数据的最佳解决方案。

我希望这会有所帮助。

答案 1 :(得分:1)

首先,您似乎不需要创建Id列,因为传入的数据文件已经具有帐户#字段,这可能为客户提供所需的唯一密钥(否则如何区分两个不同的约翰史密斯在那个文件?)。

所以你需要一个表(称之为Customer或者其他东西),有两列(如果有其他的cusomer数据要保留更多),一列叫做AccountNum,另一列叫User。使用您在上面显示的数据,它将如下所示:

          AccountNum                    User                 
          12345                         John Smith    
          98765                         Mike Jones   

和第二张表(费用表):

        AccountNum             Charges        Cost       Date
        12345                  Rental         $700       2014-10-23
        12345                  Phone          $100       2014-10-25
        98765                  Late Pay       $50        2014-10-22
        12345                  Surcharge      $100       2014-10-23

然后,每次收到新数据文件时,逐行读取,解析该行以提取帐户#值,然后查看Customer表以检查AccountNum列中是否存在该值。如果是,只需在Charges表中创建一个新记录,使用第二个表中AccountNum列的帐号。如果帐户#值不在Customer表中,则它是新客户,您必须在将该数据添加到Charges表之前在该表中创建新记录。

据推测,这些指控也有日期字段?这将区分同一客户的相同金额的两项费用。我希望这能很好地解释。