如何合并具有一对多关系的两个表

时间:2019-01-08 08:41:52

标签: sql sqlite

我有两个主要订单和订购产品的表。

Table 1: ORDERS
"CREATE TABLE IF NOT EXISTS ORDERS("
                       "id_order INTEGER PRIMARY KEY AUTOINCREMENT,
                       "o_date TEXT,"
                       "o_seller TEXT,"
                       "o_buyer TEXT,"
                       "o_shipping INTEGER,"
                       "d_amount INTEGER,"
                       "d_comm INTEGER,"
                       "d_netAmount INTEGER)"
Table 2: ORDERED_PRODUCTS
"CREATE TABLE IF NOT EXISTS dispatch_products("
                       "id_order INTEGER NOT NULL REFERENCES ORDERS(id_order),"
                       "product_name INTEGER,"
                       "quantity INTEGER,"
                       "rate INTEGER)"

我尝试使用以下查询将这两个表连接起来:

SELECT *
FROM ORDERS a
INNER JOIN ORDERED_PRODUCTS b
ON a.id_order = b.id_order
WHERE a.buyer = 'abc'

问题在于表2中包含多个产品的条目。 我得到的输出如下:

order_ID date seller buyer Ship   amt  comm nAmt Prod  Qty Rate
1             A      x       5    100  5    115  Scale 10  10
2             B      abc     10   100  5    115  pen    5  10
2             B      abc     10   100  5    115  paper 10   5
3             C      xyz     10   100  5    220  book   5  20
3             C      xyz     10   100  5    220  stapl 10  10

expected output:
order_ID date seller buyer Ship   amt  comm nAmt Prod  Qty Rate
1             A      x       5    100  5    115  Scale 10  10
2             B      abc     10   100  5    115  pen    5  10
                                                 Paper 10   5
3             C      xyz     10   100  5    220  Book   5  20
                                                 Stapl 10  10

2 个答案:

答案 0 :(得分:0)

数据库并不是真的那样工作;您得到了您想要的东西,并且没有重复(所有行都是不同的)。您正在查看来自订单的数据列,并说“哦,数据已重复”,但事实并非如此-它是“在上下文中”加入的

想象一下,我只是从您的预期输出中给了您示例行之一:

                                             Paper 10   5

保证我只是复制粘贴内容。

是什么命令?

不知道。您丢失了上下文,因此可能来自任何顺序。行是单独的实体,作为一组数据独立存在,没有引用任何其他行。这就是为什么相同的订单信息需要出现在每一行上的原因。可以制作一个数据库来产生您想要的预期输出,但是在像sqlite这样的低端数据库中,它实际上是复杂的报价。对我而言,更重要的是指出您认为查询将提供给您的内容与查询给您提供的内容之间为什么有区别的原因,因为我认为这是真正的问题:查询提供了您应有的功能,它;这是对您所得到的东西的错误假设

如果您要准备使用订单作为某种标题的报告,请在前端应用程序中单独选择它们。选择所有订单,然后一个接一个地(逐个订单)拉出所有项目明细,并随手生成报告:

myorders = dbquery("SELECT * FROM ORDERS")
for each(order o in myorders)
  print(o.header)
  details = dbquery("SELECT * FROM dispatch_products where id_order = ?", o.id)
  for each(detail d in details)
    print(d.prod, d.qty, d.rate)

答案 1 :(得分:0)

这是使数据库执行此操作的一种方法,但是您需要一个支持窗口功能(不支持3.10)或另一个数据库(SQLS> 2008,Oracle> 9或其他大型数据库)的SQLite版本过去十年左右的时间,或者是最近的MySQL):

SELECT 
  CASE WHEN rn = 1 THEN d.o_date END as o_date,
  CASE WHEN rn = 1 THEN d.o_seller END as o_seller,
  CASE WHEN rn = 1 THEN d.o_buyer END as o_buyer,
  CASE WHEN rn = 1 THEN d.o_shipping END as o_shipping,
  CASE WHEN rn = 1 THEN d.d_amount END as d_amount,
  CASE WHEN rn = 1 THEN d.d_comm END as d_comm,
  CASE WHEN rn = 1 THEN d.d_netAmount END as d_netAmount,
  d.name,
  d.qty,
  d.rate
FROM
  SELECT o.*, op.name, op.qty, op.rate, row_number() over(partition by o.id_order order by op.name, op.qty, op.rate) rn
  FROM ORDERS o
  INNER JOIN ORDERED_PRODUCTS op
  ON o.id_order = op.id_order
  WHERE o.buyer = 'abc'
) d
ORDER BY d.id_order, d.rn

我们基本上接受您的查询,添加每次订单ID更改时都会重新启动的行号,并且仅显示来自行号为1的订单表中的数据。如果您的SQLite没有row_number,则可以伪造它:{{ 3}},我将留给读者练习:)