【问题标题】:How to get aggregate and column data from Derby database joining three tables如何从连接三个表的 Derby 数据库中获取聚合和列数据
【发布时间】:2019-05-05 17:26:02
【问题描述】:

我需要在 JTable 中显示来自 Derby 数据库的数据,但其中两列是来自两个一对多相关表的汇总和。以下是示例架构:

SHIFTDATA:
    ID
    DATE
    SHIFT
    FOOD_COST
    OFFICE_SUPPLIES
    REP_MAINT
    NET_SALES
    SALES_TAX

OTHERPAIDOUTS:
    ID
    SHIFTDATA_ID
    LABEL
    AMOUNT

DISCOUNTS
    ID
    SHIFTDATA_ID
    DISCOUNT_NAME
    AMOUNT

给定的 SHIFTDATA 有 0 个或多个 OTHERPAIDOUTS

给定的 SHIFTDATA 有 0 个或多个折扣

我需要这个语句的等价物,虽然我知道我不能在 SELECT 语句中将聚合表达式与“非聚合表达式”结合起来:

SELECT (S.FOOD_COST + S.OFFICE_SUPPLIES + S.REP_MAINT + SUM(O.AMOUNT)) AS TOTAL_PAIDOUTS, 
SUM(D.AMOUNT) AS TOTAL_DISCOUNT, 
S.NET_SALES,
S.SALES_TAX
FROM SHIFTDATA S, OTHERPAIDOUTS O, DISCOUNTS D WHERE O.SHIFTDATA_ID=S.ID AND D.SHIFTDATA_ID=S.ID

我在其他线程中看到添加 GROUP BY 子句可以解决这些情况,但我想从第三个表中添加第二个聚合会让我失望。我尝试了GROUP BY S.NET_SALES、S.SALES_TAX,并在WHERE子句中加入AND S.ID = 278得到已知结果,TOTAL_PAIDOUTS正确(OTHERPAIDOUTS中有3条相关记录),但返回的TOTAL_DISCOUNTS为应该是3倍。

不用说,我不是 SQL 程序员!希望你能明白我所追求的要点。我尝试了嵌套的 SELECT 语句,但只是把它弄得一团糟。这个应用程序仍在开发中,包括数据库结构,所以如果不同的数据库结构可以简化事情,那可能是一个选择。或者,如果有另一种以编程方式构建表模型的方法,我也对此持开放态度。提前致谢!!

========编辑=============

为了检查已知记录中的值,我使用特定的 SHIFTDATA.ID 进行查询。以下是示例表记录:

SHIFTDATA:
ID  |FOOD_COST |OFFICE_SU&|REP_MAINT |NET_SALES |SALES_TAX
------------------------------------------------------
278 |0.00      |5.00      |10.00     |3898.78   |319.79

OTHERPAIDOUTS:
ID         |SHIFTDATA_&|LABEL                                   |AMOUNT
---------------------------------------------------------------------------
37         |278        |FOOD COST FUEL                          |52.00
38         |278        |MAINT FUEL                              |5.00
39         |278        |EMPLOYEE SHOES                          |21.48

DISCOUNTS:
ID         |ITEM_NAME                               |SHIFTDATA_&|AMOUNT
---------------------------------------------------------------------------
219        |Misc Discounts                          |278        |15.91

我希望在 JTable 中看到这个 SHIFTDATA 行:

TOTAL_PAIDOUTS | TOTAL_DISCOUNT |NET_SALES |SALES_TAX
------------------------------------------------------
93.48          |15.91           |3898.78   |319.79

我能得到的最好的方法是添加 GROUP BY 子句,但按我得到的 SHIFTDATA 字段分组:

TOTAL_PAIDOUTS | TOTAL_DISCOUNT |NET_SALES |SALES_TAX
------------------------------------------------------
93.48          |47.73           |3898.78   |319.79

【问题讨论】:

  • 你能举一个输入表数据的例子 - 和 - 在JTable中显示的输出吗?
  • 我将编辑我的 OP,因为我的评论长度有限。
  • 当然,。您可以在帖子底部添加它!
  • 您是如何得出93.48 对应TOTAL_PAIDOUTS 的值的?
  • 这是 S.FOOD_COST + S.OFFICE_SUPPLIES + S.REP_MAINT + SUM(O.AMOUNT) AS TOTAL_PAIDOUTS 的结果

标签: java swing derby


【解决方案1】:

试试LEFT OUTER JOIN,类似这样:

SELECT S.FOOD_COST + S.OFFICE_SUPPLIES + S.REP_MAINT + SUM(O.AMOUNT) AS TOTAL_PAIDOUTS, 
       SUM(D.AMOUNT) AS TOTAL_DISCOUNT, 
       S.NET_SALES,
       S.SALES_TAX
FROM SHIFTDATA S
LEFT JOIN OTHERPAIDOUTS AS O ON O.SHIFTDATA_ID = S.ID
LEFT JOIN DISCOUNTS AS D     ON D.SHIFTDATA_ID = S.ID

编辑

SELECT S.FOOD_COST + S.OFFICE_SUPPLIES + S.REP_MAINT +
       ( SELECT COALESCE(SUM(AMOUNT), 0) FROM OTHERPAIDOUTS WHERE SHIFTDATA_ID = S.ID ) AS TOTAL_PAIDOUTS,
       ( SELECT COALESCE(SUM(AMOUNT), 0) FROM DISCOUNTS     WHERE SHIFTDATA_ID = S.ID ) AS TOTAL_DISCOUNT,
       S.NET_SALES,
       S.SALES_TAX
FROM SHIFTDATA S

【讨论】:

  • 谢谢,但是我得到了“当 SELECT 列表包含至少一个聚合时,所有条目都必须是有效的聚合表达式”。到目前为止,我看到的所有关于将聚合与非聚合混合的问题都说必须包含 GROUP BY 子句。我唯一可以使用的 GROUP BY 子句是列出各个字段名称(S.FOOD_COST、S.OFFICE_SUPPLIES 等),TOTAL_DISCOUNT 金额是实际金额乘以每个 SHIFTDATA 的 OTHERPAIDOUTS 记录数。
  • 就是这样!非常感谢!
  • 检查一下。如果SUM(AMOUNT) FROM OTHERPAIDOUTS 不为空,则该查询返回正确的结果。如果它为空,我仍然没有得到 SHIFTDATA 列的总和。
【解决方案2】:

这是带有所需结果的 SQL 查询。

这里是表定义、数据、sql和结果:

CREATE TABLE shiftdata (
    id int,
    foodcost int,
    officesuppl int,
    repmaint int,
    netsales int,
    salestax int);

CREATE TABLE otherpaidouts (
    id int,
    shiftid int,
    label varchar(20),
    amount int);

CREATE TABLE discounts (
    id int,
    shiftid int,
    itemname varchar(20),
    amount int);

为两个班次创建数据:278 和 333。两个班次都有discounts,但只有 278 班次有otherpaidouts

insert into shiftdata values (278, 0, 5, 10, 3898, 319);
insert into shiftdata values (333, 22, 15, 100, 2111, 88);
insert into otherpaidouts values (37, 278, 'Food Cost FUEL', 52);
insert into otherpaidouts values (38, 278, 'Maint FUEL', 5);
insert into otherpaidouts values (39, 278, 'Empl SHOES', 21);
insert into discounts values (219, 278, 'Misc DISCOUNTS', 15);
insert into discounts values (312, 333, 'Misc DISCOUNTS', 25);


查询:

SELECT sd.id, sd.netsales, sd.salestax,
  IFNULL(
    (SELECT SUM(d.amount) FROM discounts d WHERE d.shiftid=sd.id), 0) AS total_discount,
  (SELECT sd.foodcost + sd.officesuppl + sd.repmaint + IFNULL(SUM(op.amount), 0) FROM otherpaidouts op WHERE op.shiftid=sd.id) AS total_paidouts
FROM shiftdata sd;


结果:

+------+----------+----------+----------------+----------------+
| id   | netsales | salestax | total_discount | total_paidouts |
+------+----------+----------+----------------+----------------+
|  278 |     3898 |      319 |             15 |             93 |
|  333 |     2111 |       88 |             25 |            137 |
+------+----------+----------+----------------+----------------+

【讨论】:

  • 男人。看起来确实不错,但我在 Derby 中没有看到 IFNULL 函数。
  • 男人。我知道你在做某事。我确实找到了COALESCE 函数,它的工作原理完全相同!你做到了!非常非常感谢!你做了很多工作,非常感谢。
  • 是的,我在想MYSQL(MySQL 有COALESCE)!是的,我在 Apache Derby(又名 JavaDB)上做了一点工作,但感谢您指出。 SO上大部分数据库相关的帖子都是MySQL,我没注意到是Derby。
猜你喜欢
  • 1970-01-01
  • 2012-01-05
  • 2011-01-20
  • 2016-02-02
  • 1970-01-01
  • 2017-12-20
  • 1970-01-01
  • 2020-03-13
  • 2023-03-07
相关资源
最近更新 更多