如何从连接三个表的 Derby 数据库中获取聚合和列数据

How to get aggregate and column data from Derby database joining three tables

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

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 语句中将聚合表达式与 "non-aggregate expressions" 结合起来:

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 子句可以解决这些情况,但我想从第三个 table 添加到第二个聚合会让我失望。我试过 GROUP BY S.NET_SALES, S.SALES_TAX, 并在 WHERE 子句中添加 AND S.ID = 278 得到一个已知的结果,TOTAL_PAIDOUTS 是正确的(有 3 个相关OTHERPAIDOUTS 中的记录),但返回的 TOTAL_DISCOUNTS 是应有的 3 倍。

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

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

为了检查已知记录的值,我正在查询特定的 SHIFTDATA.ID。以下是示例 table 记录:

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

试试 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

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

这里是 table 定义、数据、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 |
+------+----------+----------+----------------+----------------+