-2

我有一个客户表,其中包含有关客户偏好的信息,例如他是否想接收时事通讯等。如果他/她想要接收时事通讯,则该值存储在“customerNewsletter”列中并设置为 true。但是,我有几个这些位值和参数位于自己的列中。我为每个客户存储日期、真/假、整数和 tekst。

我发现大约 80% 的客户希望收到时事通讯,这使得 80% 的值设置为 true。我现在为每个设置为 false 或 true 的客户存储一个值。如果我只需要将 20% 设置为 false 怎么办?

有一个包含大约 20 个这些参数的列表,我可以将它们作为一列包含(它们现在是),但我想知道是否有更好的方法。

所以我创建了 3 个表来保存这些参数值,一个保存实际值的 param 表,一个保存值名称的 paramsNames 表,以及一个将参数连接到 customerID 的 params 表

SELECT 
customerParamsName as [Name],
customerParamText as [Text],
customerParamINT as [int],
customerParamsDateTime as [Date] 
FROM db14.customerParams
INNER JOIN db14.customerParam ON customerParamsChildID = customerParamID
INNER JOIN db14.customerParamsNames ON customerParamNameID = customerParamsNameID

这会给我

Name         Text         int   Date
Phonenumber  NULL   615164898   2013-09-20 00:00:00.000

谁能告诉我这是否是一个好方法,还是有更有效的存储多类型参数的常用方法?


经过更多的考虑

我创建了 2 个表

客户参数

paramID  paramNameID  ParamParentID  paramChildID  paramText    paramINT  paramDate
INT      TINYINT      INT            INT           varchar(24)  INT       DATETIME
PRIMARY               INDEXED

客户参数名称

paramNameID    paramName
TINYINT        VARCHAR(24)
PRIMARY

          1    'FirstName'
          2    'LastName'
          3    'Email Address'
          4    'Phonenumber'
          5    etc..

假设我想存储 firstName 和 LastName

我在 customerParam 中为这两个值创建记录;

paramID  paramNameID  ParamParentID  paramChildID  paramText    paramINT     paramDate
17456              1                               'John'
17467              2                               'Doo'
17468              1            752         17456
17469              2            752         17467

由于我预计名称“John”会出现更多,我将其存储为独立值,然后使用 parentID/ChildID 组合加入它。

和电话号码

17470              4            752                             31615164899            
17471              5            752                'me@here.com'

电话号码对这个客户非常明确,我使用 parentID 将其直接加入客户。电子邮件地址也是如此。

目前这个解决方案看起来像是要走的路......我还在研究 xml 方法,但我对如何使用存储在数据库中的 XQuery 和 xmlDocuments 没有很好的理解。这似乎是很多开销。

我将继续使用上面的解决方案......直到有人给我一个更好的解决方案。

示例 SQL

DECLARE @paramNames TABLE (paramNameID TINYINT, paramName varchar(24))

DECLARE @param TABLE (paramID INT, paramNameID TINYINT, paramParentID INT, paramChildID INT, paramText varchar(24), paramINT INT, paramDate datetime)

INSERT INTO @paramNames VALUES ( 1, 'firstname')
INSERT INTO @paramNames VALUES ( 2, 'lastname')
INSERT INTO @paramNames VALUES ( 3, 'emailaddress')
INSERT INTO @paramNames VALUES ( 4, 'phonenumber')

select * from @paramNames

INSERT INTO @param VALUES (1, 1, Null, Null, 'John' , Null, Null)
INSERT INTO @param VALUES (2, 2, Null, Null, 'Doo' , Null, Null)
INSERT INTO @param VALUES (3, 1, 752, 1, Null , Null, Null)
INSERT INTO @param VALUES (4, 2, 752, 2, Null , Null, Null)
INSERT INTO @param VALUES (5, 4, 752, Null, Null , 615164899, Null)
INSERT INTO @param VALUES (5, 3, 752, Null, 'me@here.com' , Null, Null)

select 
a.paramParentID, b.paramName, c.paramText, c.paramINT, c.paramDate
from @param a
inner join @paramNames b on a.paramNameID = b.paramNameID
inner join @param c on a.paramChildID = c.paramID
UNION ALL
select 
a.paramParentID, b.paramName, a.paramText, a.paramINT, a.paramDate
from @param a
inner join @paramNames b on a.paramNameID = b.paramNameID
WHERE paramParentID IS NOT NULL
AND paramChildID IS NULL

给出结果

paramParentID   paramName       paramText   paramINT    paramDate
752             firstname       John        NULL        NULL
752             lastname        Doo         NULL        NULL
752             phonenumber     NULL        615164899   NULL
752             emailaddress    me@here.com NULL        NULL
4

2 回答 2

2

如果您考虑到性能和灵活性,我会以不同的方式处理这个问题。

USE Test;

CREATE TABLE Customers
(
    CustomerID INT NOT NULL CONSTRAINT PK_Customers 
                 PRIMARY KEY CLUSTERED IDENTITY(1,1)
    , CustomerName NVARCHAR(255)
);

CREATE TABLE CustomersReceivingEmails
(
    CustomerID INT NOT NULL CONSTRAINT FK_CustomerID 
                 FOREIGN KEY REFERENCES Customers (CustomerID)
                 ON DELETE CASCADE ON UPDATE CASCADE
    , EmailAddress NVARCHAR(255) NOT NULL
    CONSTRAINT PK_CustomersReceivingEmails 
                 PRIMARY KEY CLUSTERED (CustomerID, EmailAddress)
);

INSERT INTO Customers (CustomerName) VALUES ('Max');
INSERT INTO Customers (CustomerName) VALUES ('Mike');

INSERT INTO CustomersReceivingEmails (CustomerID, EmailAddress) 
        VALUES (1, 'us@them.com');
INSERT INTO CustomersReceivingEmails (CustomerID, EmailAddress) 
        VALUES (1, 'us@me.com');

/* ALL Customers */
SELECT * FROM Customers;

/* Only customers who wish to receive Emails, allows a given customer 
    to have multiple email addresses */
SELECT C.CustomerName, E.EmailAddress 
FROM Customers C 
    INNER JOIN CustomersReceivingEmails E ON C.CustomerID = E.CustomerID
ORDER BY C.CustomerName, E.EmailAddress;

返回行SELECT如下:

在此处输入图像描述

这允许Customers表格包含所有客户,无论他们对电子邮件的偏好如何。

对于想要接收电子邮件的客户,该CustomersReceivingEmails表有一个外键。Customers.CustomerID

于 2013-09-20T04:21:14.837 回答
1

您的第二个解决方案是通常称为实体-属性-值数据模型的变体。这种方法似乎很灵活。但是,它本质上是在模式中生成模式,并且随着属性数量的增加,查询速度非常慢

如果您要存储许多相同的值,请查看columnstore 索引。它们在选择性低的情况下工作良好(很多行和只有少数不同的值)

于 2013-09-24T10:42:21.810 回答