解释行和列依赖项

时间:2009-07-09 16:00:27

标签: database database-design

这是一个简单而常见的工作方案,我很感激一些意见。

假设我正在为宠物秀的主人制作报告,他们想知道他们的哪些顾客已经购买了每只宠物的数量。在这种情况下,我唯一的工具是SQL,可以将我的查询输出到电子表格。

作为店主,我可能希望报告形式为:

Customer  Dog  Cat  Rabbit
1         2    3    0
2         0    1    1
3         1    2    0
4         0    0    1

如果有一天我决定库存金鱼,那么报告现在就应该出来了。

Customer  Dog  Cat  Rabbit Goldfish
1         2    3    0      0
2         0    1    1      0
3         1    2    0      0
4         0    0    1      0
5         0    0    0      1

但正如您可能知道的那样,以这种方式运行的查询将涉及某种形式的动态代码生成,并且将更难做到。

最简单的查询将按以下方式工作: 交叉加入客户和宠物,外部加入销售,集团等 并生成:

Customer Pet      Quantity
1        Dog      2
1        Cat      3
1        Rabbit   0
1        Goldfish 0
2        Dog      0
2        Cat      1
2        Rabbit   1
...etc

a)我如何向店主解释他们想要的报告“难以”产生?我并不想说它更难读,但写起来更难。

b)我试图向客户解释的概念的名称是什么(以帮助我的谷歌搜索)?

4 个答案:

答案 0 :(得分:2)

概念的名称是“交叉表”,可以通过多种方式完成。

MS Access具有SQL专有扩展,可以实现这一目标。 SQL pre-2k5有一个CASE技巧和2k5后来有PIVOT,但我认为你仍然需要知道列是什么。

答案 1 :(得分:1)

有些数据库确实支持某种创建交叉表的方法,但我认为最需要知道的 提前列,所以你必须修改SQL(并获得支持这种扩展的数据库)。

另一种方法是创建一个程序,该程序将对第二个“简单”表进行后处理,以使客户端作为输出交叉表。与修改SQL或动态生成SQL相比,这可能更容易,也更通用。

关于解释问题的方法......你可以在Excel中显示它们需要多少步骤来获得所需的结果:

  • 源数据(您的第二个列表)。
  • 从宠物栏中选择值
  • 将每个宠物类型放在新列上
  • 每个客户的每种类型的值计算
  • 填写值

然后说SQL只为你提供源数据,所以它当然更有效。

答案 2 :(得分:1)

此概念称为pivoting

SQL假设您的数据是以具有固定结构的关系表示的。

就像,平等是二元关系,“顾客有这种类型的许多宠物”是三元关系等等。

当您看到此结果集时:

Customer Pet      Quantity
1        Dog      2
1        Cat      3
1        Rabbit   0
1        Goldfish 0
2        Dog      0
2        Cat      1
2        Rabbit   1

,它实际上是由值的所有可能组合定义的关系。

例如,客户1(域customers id's)拥有2属的positive numbers(域dog)宠物(域名pets} )。

我们在结果集中看不到这样的行:

Customer Pet      Quantity
1        Dog      3
Pete     Wife     0.67

,因为第一行为false(客户1没有3dog,但2),第二行的值不在他们的域名范围。

SQL范例意味着在发出查询时定义了您的关系,并且返回的每一行都完全定义了关系。

SQL Server 2005+可以将行映射到列中(这就是您想要的),但在设计查询(未运行)时应该知道列数。

通常,您尝试构建的报告是使用报告软件构建的,该软件知道如何将关系SQL结果集转换为漂亮的人类可读报告。

答案 3 :(得分:1)

我一直称这种旋转,但这可能不是正式名称。

无论它被称为什么,你都可以用普通的SQL做几乎所有这些。

SELECT customer, count(*), sum(CASE WHEN pet='dog' THEN 1 ELSE 0 END) as dog, sum(case WHEN pet='cat' THEN 1 ELSE 0 END) as cast FROM customers join pets

显然缺少的是动态列。我不知道这是否可以在直接SQL中使用,但在存储过程中当然可以在首次查询宠物列表后动态生成查询。查询构建在一个字符串中,然后该字符串用于创建预准备语句。