我无法获得此mysql连接查询以产生所需的结果

时间:2012-05-18 11:43:21

标签: mysql

三个表的结构。

预订

CREATE TABLE `booking` (
`bookingID` int(11) NOT NULL AUTO_INCREMENT,
`receipt_no` int(11) NOT NULL,
`client` varchar(32) NOT NULL,
`operator` varchar(32) NOT NULL,
`discount` int(11) NOT NULL,
`total_amount` int(64) NOT NULL,
`amount_paid` int(32) NOT NULL,
`balance` int(32) NOT NULL,
`date` date NOT NULL,
PRIMARY KEY (`bookingID`)
ENGINE=InnoDB AUTO_INCREMENT=209 DEFAULT CHARSET=latin1

JOBTITLE

CREATE TABLE `jobtitle` (
`jobtitleID` int(11) NOT NULL AUTO_INCREMENT,
`jobtitle` varchar(255) NOT NULL,
`quantity` int(11) NOT NULL,
`amount` varchar(255) NOT NULL,
`jobtypeID` int(11) NOT NULL,
`bookingID` int(11) NOT NULL,
PRIMARY KEY (`jobtitleID`)
ENGINE=InnoDB AUTO_INCREMENT=463 DEFAULT CHARSET=latin1

First_graphics_debtors

CREATE TABLE `first_graphics_debtors`
`id` int(11) NOT NULL AUTO_INCREMENT,
`receipt_no` int(11) NOT NULL,
`date_paid` date NOT NULL,
`old_balance` int(32) NOT NULL,
`debtor_amount_paid` int(32) NOT NULL,
`new_balance` int(32) NOT NULL,
PRIMARY KEY (`id`)
ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=latin1

插入少量数据后

预订

+-----------+------------+----------+----------+----------+--------------+-------------+---------+------------+
| bookingID | receipt_no | client   | operator | discount | total_amount | amount_paid | balance | date       |
+-----------+------------+----------+----------+----------+--------------+-------------+---------+------------+
|       205 |  156872940 | Osaro    | Obi      |       10 |       156380 |      135000 |    5742 | 2012-05-15 |
|       206 |  227349168 | Amaka    | Stephen  |        4 |        73250 |       70320 |       0 | 2012-05-15 |
|       207 |  155732278 | Aghahowa | Ibori    |        0 |       116836 |       15000 |  101836 | 2012-05-15 |
|       208 |  753263343 | Chaka    | Stephen  |       10 |       231290 |       56000 |  152161 | 2012-05-15 |
+-----------+------------+----------+----------+----------+--------------+-------------+---------+------------+

JOBTITLE

+------------+---------------------------+----------+--------+-----------+-----------+
| jobtitleID | jobtitle                  | quantity | amount | jobtypeID | bookingID |
+------------+---------------------------+----------+--------+-----------+-----------+
|        454 | A1 Full Colour            |       10 | 4334   |         1 |       205 |
|        455 | Complementry Card         |       20 | 5652   |         2 |       205 |
|        456 | A4 Printout (graphics)B/W |       25 | 2930   |         4 |       206 |
|        457 | Scan                      |        2 | 4334   |         5 |       207 |
|        458 | A4 Full Colour            |      199 | 500    |         3 |       207 |
|        459 | ID Card                   |        2 | 4334   |         2 |       207 |
|        460 | A3 Full Colour            |       10 | 4334   |         3 |       208 |
|        461 | Flex Banner               |       20 | 2930   |         2 |       208 |
|        462 | A2 Single Colour          |      199 | 650    |         1 |       208 |
+------------+---------------------------+----------+--------+-----------+-----------+

First_graphics_debtors

+----+------------+------------+-------------+--------------------+-------------+
| id | receipt_no | date_paid  | old_balance | debtor_amount_paid | new_balance |
+----+------------+------------+-------------+--------------------+-------------+
|  7 |  156872940 | 2012-05-15 |        5742 |               5000 |         742 |
|  8 |  156872940 | 2012-05-15 |        5742 |               5742 |           0 |
|  9 |  753263343 | 2012-05-15 |      152161 |             152161 |           0 |
| 13 |  753263343 | 2012-05-15 |      152161 |              14524 |      137637 |
| 14 |  753263343 | 2012-05-15 |      152161 |               2000 |      150161 |
| 15 |  753263343 | 2012-05-15 |      152161 |               1000 |      151161 |
+----+------------+------------+-------------+--------------------+-------------+

当我运行此查询时:

SELECT `booking`.`receipt_no`, `client`, `operator`, `discount`, `total_amount`,
       `amount_paid`, `balance`, `date`, `jobtitle`, `quantity`, `amount`,
       `date_paid`, `old_balance`, `debtor_amount_paid`, `new_balance`
  FROM (`booking`)
  JOIN `jobtitle` ON `jobtitle`.`bookingID` = `booking`.`bookingID`
  JOIN `first_graphics_debtors`
    ON `first_graphics_debtors`.`receipt_no` = `booking`.`receipt_no`
 WHERE `booking`.`receipt_no` =  '753263343'
   AND `first_graphics_debtors`.`receipt_no` =  '753263343'
 GROUP BY `jobtitle`.`quantity`

我得到了这个输出:

+------------+--------+----------+----------+--------------+-------------+---------+------------+------------------+----------+--------+------------+-------------+--------------------+-------------+
| receipt_no | client | operator | discount | total_amount | amount_paid | balance | date       | jobtitle         | quantity | amount | date_paid  | old_balance | debtor_amount_paid | new_balance |
+------------+--------+----------+----------+--------------+-------------+---------+------------+------------------+----------+--------+------------+-------------+--------------------+-------------+
|  753263343 | Chaka  | Stephen  |       10 |       231290 |       56000 |  152161 | 2012-05-15 | A3 Full Colour   |       10 | 4334   | 2012-05-15 |      152161 |             152161 |           0 |
|  753263343 | Chaka  | Stephen  |       10 |       231290 |       56000 |  152161 | 2012-05-15 | Flex Banner      |       20 | 2930   | 2012-05-15 |      152161 |             152161 |           0 |
|  753263343 | Chaka  | Stephen  |       10 |       231290 |       56000 |  152161 | 2012-05-15 | A2 Single Colour |      199 | 650    | 2012-05-15 |      152161 |             152161 |           0 |
+------------+--------+----------+----------+--------------+-------------+---------+------------+------------------+----------+--------+------------+-------------+--------------------+-------------+

以下列的数据重复三次,而不是从与receipt_no相关的四行中获取数据

date_paid, old_balance, debtor_amount_paid, new_balance

预期结果

+------------+--------+----------+----------+--------------+-------------+---------+------------+------------------+----------+--------+------------+-------------+--------------------+-------------+
| receipt_no | client | operator | discount | total_amount | amount_paid | balance | date       | jobtitle         | quantity | amount | date_paid  | old_balance | debtor_amount_paid | new_balance |
+------------+--------+----------+----------+--------------+-------------+---------+------------+------------------+----------+--------+------------+-------------+--------------------+-------------+
|  753263343 | Chaka  | Stephen  |       10 |       231290 |       56000 |  152161 | 2012-05-15 | A3 Full Colour   |       10 | 4334   | 2012-05-15 |      152161 |             152161 |           0 |
|  753263343 | Chaka  | Stephen  |       10 |       231290 |       56000 |  152161 | 2012-05-15 | Flex Banner      |       20 | 2930   | 2012-05-15 |      152161 |             14524  |     137637  |
|  753263343 | Chaka  | Stephen  |       10 |       231290 |       56000 |  152161 | 2012-05-15 | A2 Single Colour |      199 | 650    | 2012-05-15 |      152161 |             2000   |      150161 |
+------------+--------+----------+----------+--------------+-------------+---------+------------+------------------+----------+--------+------------+-------------+--------------------+-------------+

尽管如此,预期的输出尚未完成,但也许您可以从debtor_amount_paidnew_balance上的数据中获取图片

3 个答案:

答案 0 :(得分:1)

我很确定你的问题是因为你的GROUP BY条款。不确定你使用它的目的是什么,但尝试没有它。如果您获得重复的行,请尝试使用SELECT DISTINCT。如果您的目标是根据该列订购结果,请使用ORDER BY

此外,在receipt_no子句中指定WHERE两次是多余的。这两个表已经被该列连接,因此您需要在一个表中对其进行过滤。并且除了一些特殊的异常(例如列名中的空格或逗号)或者与保留字命名相同的列(也可能是其他几个)之外,反引号并不是必需的。您的唯一一列看起来需要反引号是date列,但即使在该列上排除它们,您仍应该没问题。我发现到处都是反复使得查询更长,更难阅读。他们不会因为在那里而伤害任何东西,所以如果这是你的偏好,你可以留下他们,但就个人而言,我不是粉丝。

我用上面提到的修改重写了你的查询,而且我给表别名以进一步缩短它。这不会提高性能或任何东西,只是让它更容易阅读IMO:

SELECT DISTINCT
    b.receipt_no, client, operator, discount, total_amount,
    amount_paid, balance, `date`, jobtitle, quantity,
    amount, date_paid, old_balance, debtor_amount_paid, new_balance
FROM
    booking b
    INNER JOIN jobtitle jt ON jt.bookingID = b.bookingID
    INNER JOIN first_graphics_debtors fgd ON fgd.receipt_no = b.receipt_no
WHERE
    b.receipt_no = '753263343'
ORDER BY
    jt.quantity

答案 1 :(得分:1)

您可能希望使用FULL JOIN来对齐这些连接的行,但由于MySQL上没有FULL JOIN,您必须与UNION竞争:

压缩代码以避免滚动条:

select bx.*, null as sepy, booking_particulars.*
from booking bx 
join (
  select same_n, 
     max(Receipt_No) as Receipt_No, max(Quantity) as Quantity,  
     max(Amount) as Amount, 
     null as sepx, -- separator      
     max(Date_Paid) as Date_Paid, max(Old_Balance) as Old_Balance, 
     max(Debtor_Amount_Paid) as Debtor_Amount_Paid, 
     max(New_Balance) as New_Balance
  from (
    select *                
    from (
      select b.Receipt_No, j.Quantity, j.Amount,           
        null as Date_Paid, null as Old_Balance, null as Debtor_Amount_Paid, 
        null as New_Balance, @j_rn := @j_rn + 1 as same_n            
      from (booking b, (select @j_rn := 0) as vars) 
      join jobtitle j ON j.bookingID = b.bookingID
      where b.receipt_no =  '753263343' 
      order by j.JobTitleId
    ) as jx
    union all
    select * from (
      select f.Receipt_No, null as Quantity, null as Amount,             
        f.Date_Paid, f.Old_Balance, f.Debtor_Amount_Paid, 
        f.New_Balance, @f_rn := @f_rn + 1 as same_n          
      from (first_graphics_debtors f, (select @f_rn := 0) as vars)
      where f.receipt_no = '753263343' 
      order by f.id
    ) as fx
  ) as z
  group by same_n order by same_n
) as booking_particulars on booking_particulars.receipt_no = bx.receipt_no

输出:

| BOOKINGID | RECEIPT_NO | CLIENT | OPERATOR | DISCOUNT | TOTAL_AMOUNT | AMOUNT_PAID | BALANCE |                       DATE |   SEPY | SAME_N | QUANTITY | AMOUNT |   SEPX |                  DATE_PAID | OLD_BALANCE | DEBTOR_AMOUNT_PAID | NEW_BALANCE |
|-----------|------------|--------|----------|----------|--------------|-------------|---------|----------------------------|--------|--------|----------|--------|--------|----------------------------|-------------|--------------------|-------------|
|       208 |  753263343 |  Chaka |  Stephen |       10 |       231290 |       56000 |  152161 | May, 15 2012 08:00:00-0700 | (null) |      1 |       10 |   4334 | (null) | May, 15 2012 08:00:00-0700 |      152161 |             152161 |           0 |
|       208 |  753263343 |  Chaka |  Stephen |       10 |       231290 |       56000 |  152161 | May, 15 2012 08:00:00-0700 | (null) |      2 |       20 |   2930 | (null) | May, 15 2012 08:00:00-0700 |      152161 |              14524 |      137637 |
|       208 |  753263343 |  Chaka |  Stephen |       10 |       231290 |       56000 |  152161 | May, 15 2012 08:00:00-0700 | (null) |      3 |      199 |    650 | (null) | May, 15 2012 08:00:00-0700 |      152161 |               2000 |      150161 |
|       208 |  753263343 |  Chaka |  Stephen |       10 |       231290 |       56000 |  152161 | May, 15 2012 08:00:00-0700 | (null) |      4 |   (null) | (null) | (null) | May, 15 2012 08:00:00-0700 |      152161 |               1000 |      151161 |

在此处进行实时测试和查询进展:http://www.sqlfiddle.com/#!2/d8d3b/45

答案 2 :(得分:0)

我完全同意Travesty3关于表别名和反引号的内容。

我认为,您的问题是,您正试图将“应该”和“应该”的内容结合起来。是两个单独的查询到一个。对于任何给定的预订,您可以拥有任意数量的职位条目,并且完全独立于职位信息,您可以拥有任意数量的First Graphics Debtors条目。在样品收据753263343的样本数据中,您有一个预订,三个职称条目和4个第一图形债务人条目。

默认情况下(没有GROUP BY子句),您将得到12个条目,对应于三组行的交叉积(1 x 3 x 4)。

MySQL中的GROUP BY与大多数其他DBMS不同;标准SQL不允许您省略GROUP BY子句中的非聚合列(并且所有列都是非聚合的)。

我认为您之后的输出结果集类似于(使用FGD作为First Graphics Debtors的缩写):

+-------------------+---------------------+---------------+
| Data from Booking | Data from Job Title | Data from FGD |
+-------------------+---------------------+---------------+
| Booking ID 208... | Job Title ID 460... | FGD ID 9      |
| Booking ID 208... | Job Title ID 461... | FGD ID 13     |
| Booking ID 208... | Job Title ID 462... | FGD ID 14     |
| Booking ID 208... | ...?????????????... | FGD ID 15     |
+-------------------+---------------------+---------------+

问号的最合理的值集可能是一组NULL。

但是,您可能会更好,使用两个单独的查询,一个用于获取职位信息,一个用于获取FGD信息(两个中只有一个需要返回预订信息)。但是,您必须在应用程序代码中进行一些演示工作(这是应该进行演示工作的地方,但这是一个不同的讨论)。

因此,对于胆小的人,我建议使用两个查询。对于勇敢者,请继续阅读...


勇敢

更新: TDQD - 包括测试的材料有点错误。

首先,让我说明一下:如果这是你所追求的,那么这是相对艰苦的工作,尽管可以做到。其次,它在DBMS中使用OLAP函数更简单。使用MySQL(以及其他一些DBMS),您可以使用临时表来保存中间结果。

您在预订ID上加入预订和职位。您在收据编号上加入Booking和FGD。假设我们创建了两个中间结果集:

SequencedJobTitles(Booking ID, Job_Seq_No)
SequencedReceipts(Receipt No, Rec_Seq_No)

其中第一个作业序列号从每个预订ID的1..N开始,每个收据号的收据序列号从1..M开始。

现在我们可以写:

SELECT B.*, J.*, R.*
  FROM Booking AS B
  LEFT JOIN (SELECT J1.*, J2.Job_Seq_No
               FROM SequencedJobTitles AS J2
               JOIN JobTitle           AS J1 ON J2.BookingID = J1.BookingID
            ) AS J
    ON B.BookingID = J.BookingID
  LEFT JOIN (SELECT R1.*, R2.Rec_Seq_No
               FROM SequencedReceipts      AS R2
               JOIN First_Graphics_Debtors AS R1 ON R1.Receipt_No = R2.Receipt_No
            ) AS R
 WHERE J.Job_Seq_No = R.Rec_Seq_No
   AND B.Receipt_No = 753263343
 ORDER BY B.BookingID, COALESCE(J2.Job_Seq_No, R2.Rec_Seq_No);

是的,使用*是懒惰的;我对其进行了优化,以列出生产查询中我想要的列的确切列表。对于调试,它可以确保您查看所有数据,这可能会有所帮助。

如何创建两个中间结果集?

如果没有OLAP功能,您可以使用以下命令生成SequencedJobTitles:

SELECT J1.BookingID, COUNT(*) AS Job_Seq_No
  FROM JobTitle AS J1
  JOIN JobTitle AS J2
    ON J1.BookingID = J2.BookingID
 WHERE J1.JobTitleID <= J2.JobTitleID
 GROUP BY J1.BookingID;

与SequencedReceipts类似:

SELECT R1.Receipt_No, COUNT(*) AS Rec_Seq_No
  FROM First_Graphics_Debtors AS R1
  JOIN First_Graphics_Debtors AS R2
    ON R1.Receipt_No = R2.Receipt_No
 WHERE R1.ID <= R2.ID
 GROUP BY R1.Receipt_No;

这些表达式使用非等值连接的自连接,这是非常昂贵的。如果表格很大,您可能希望仅将相关的预订ID或收据号码限制在子查询中。请注意,您可以单独测试这些子查询;这对于TDQD(测试驱动查询设计)来说是一个好主意。

但是,我们可以简单地将这些子查询插入到之前开发的主查询中:

SELECT B.*, J.*, R.*
  FROM Booking AS B
  LEFT JOIN (SELECT J1.*, J2.Job_Seq_No
               FROM (SELECT J1.BookingID, COUNT(*) AS Job_Seq_No
                      FROM JobTitle AS J1
                      JOIN JobTitle AS J2
                        ON J1.BookingID = J2.BookingID
                     WHERE J1.JobTitleID <= J2.JobTitleID
                     GROUP BY J1.BookingID
                    ) AS J2
               JOIN JobTitle AS J1 ON J2.BookingID = J1.BookingID
            ) AS J
    ON B.BookingID = J.BookingID
  LEFT JOIN (SELECT R1.*, R2.Rec_Seq_No
               FROM (SELECT R1.Receipt_No, COUNT(*) AS Rec_Seq_No
                      FROM First_Graphics_Debtors AS R1
                      JOIN First_Graphics_Debtors AS R2
                        ON R1.Receipt_No = R2.Receipt_No
                     WHERE R1.ID <= R2.ID
                     GROUP BY R1.Receipt_No
                    ) AS R2
               JOIN First_Graphics_Debtors AS R1 ON R1.Receipt_No = R2.Receipt_No
            ) AS R
    ON J.Job_Seq_No = R.Rec_Seq_No
 WHERE B.Receipt_No = 753263343
 ORDER BY B.BookingID, COALESCE(J2.Job_Seq_No, R2.Rec_Seq_No);

警告:未经测试的SQL!

更新:这个警告没有放在那里。无论我怎么努力,我都不相信自己第一次准确地编写复杂的查询。而且我并没有尝试制作我之前展示的轮廓结果(我总是使用两个单独的查询并将数据组合在演示工具方法中),所以我认为错误是不可避免的。 / p>

TDQD - 包括测试

Real TDQD显示序列查询很接近,但不正确。虽然我将<=条件更改为>=条件,但这更具有外观性而非实质性。正确的查询如下:

SELECT J1.BookingID, J1.JobTitleID, COUNT(*) AS Job_Seq_No
  FROM JobTitle AS J1
  JOIN JobTitle AS J2
    ON J1.BookingID = J2.BookingID
 WHERE J1.JobTitleID >= J2.JobTitleID
 GROUP BY J1.BookingID, J1.JobTitleID;

SELECT R1.Receipt_No, R1.ID, COUNT(*) AS Rec_Seq_No
  FROM First_Graphics_Debtors AS R1
  JOIN First_Graphics_Debtors AS R2
    ON R1.Receipt_No = R2.Receipt_No
 WHERE R1.ID >= R2.ID
 GROUP BY R1.Receipt_No, R1.ID;

这两个结果可以用相应的表连接起来,但是连接条件与我最初写的不同:

SELECT J4.*, J3.Job_Seq_No
  FROM (SELECT J1.BookingID, J1.JobTitleID, COUNT(*) AS Job_Seq_No
          FROM JobTitle AS J1
          JOIN JobTitle AS J2
            ON J1.BookingID = J2.BookingID
         WHERE J1.JobTitleID >= J2.JobTitleID
         GROUP BY J1.BookingID, J1.JobTitleID
        ) AS J3
  JOIN JobTitle AS J4
    ON J3.BookingID  = J4.BookingID
   AND J3.JobTitleID = J4.JobTitleID
 ORDER BY J4.BookingID, J3.Job_Seq_No;

SELECT R4.*, R3.Rec_Seq_No
  FROM (SELECT R1.Receipt_No, R1.ID, COUNT(*) AS Rec_Seq_No
          FROM First_Graphics_Debtors AS R1
          JOIN First_Graphics_Debtors AS R2
            ON R1.Receipt_No = R2.Receipt_No
         WHERE R1.ID >= R2.ID
         GROUP BY R1.Receipt_No, R1.ID
        ) AS R3
   JOIN First_Graphics_Debtors AS R4
     ON R3.Receipt_No = R4.Receipt_No
    AND R3.ID         = R4.ID
  ORDER BY R4.Receipt_No, R3.Rec_Seq_No;

然后你可以运行这个查询:

SELECT B.*, J.*, R.*
  FROM Booking AS B
  LEFT JOIN (SELECT J4.*, J3.Job_Seq_No
               FROM (SELECT J1.BookingID, J1.JobTitleID, COUNT(*) AS Job_Seq_No
                       FROM JobTitle AS J1
                       JOIN JobTitle AS J2
                         ON J1.BookingID = J2.BookingID
                      WHERE J1.JobTitleID >= J2.JobTitleID
                      GROUP BY J1.BookingID, J1.JobTitleID
                     ) AS J3
               JOIN JobTitle AS J4
                 ON J3.BookingID  = J4.BookingID
                AND J3.JobTitleID = J4.JobTitleID
            ) AS J
    ON B.BookingID = J.BookingID
  LEFT JOIN (SELECT R4.*, R3.Rec_Seq_No
               FROM (SELECT R1.Receipt_No, R1.ID, COUNT(*) AS Rec_Seq_No
                       FROM First_Graphics_Debtors AS R1
                       JOIN First_Graphics_Debtors AS R2
                         ON R1.Receipt_No = R2.Receipt_No
                      WHERE R1.ID >= R2.ID
                      GROUP BY R1.Receipt_No, R1.ID
                     ) AS R3
                JOIN First_Graphics_Debtors AS R4
                  ON R3.Receipt_No = R4.Receipt_No
                 AND R3.ID         = R4.ID
            ) AS R
    ON B.Receipt_No = R.Receipt_No
 WHERE B.Receipt_No = 753263343
   AND J.Job_Seq_No = R.Rec_Seq_No
 ORDER BY B.BookingID, NVL(J.Job_Seq_No, R.Rec_Seq_No);

不幸的是,它只在样本数据上产生三行;它省略了4个收据号码中的最后一个。这就是我做TDQD的原因;当我采取捷径时,我发现存在问题。

最后一个查询的结构需要使用FULL OUTER JOIN(通常)连接J和R子查询,因此它们需要共同的收据号或预订ID。我选择将收据编号添加到JobTitle信息中;将预订ID添加到First Graphics Debtors信息可以正常工作;对称性表明两者兼顾,但这也可能被视为过度杀伤。

SELECT B.Receipt_No, J4.*, J3.Job_Seq_No
  FROM (SELECT J1.BookingID, J1.JobTitleID, COUNT(*) AS Job_Seq_No
          FROM JobTitle AS J1
          JOIN JobTitle AS J2
            ON J1.BookingID = J2.BookingID
         WHERE J1.JobTitleID >= J2.JobTitleID
         GROUP BY J1.BookingID, J1.JobTitleID
        ) AS J3
  JOIN JobTitle AS J4
    ON J3.BookingID  = J4.BookingID
   AND J3.JobTitleID = J4.JobTitleID
  JOIN Booking  AS B
    ON B.BookingID = J4.BookingID
 ORDER BY J4.BookingID, J3.Job_Seq_No;

然后,将两个排序列表与FULL OUTER JOIN组合:

SELECT *
  FROM (SELECT B.Receipt_No, J4.*, J3.Job_Seq_No
          FROM (SELECT J1.BookingID, J1.JobTitleID, COUNT(*) AS Job_Seq_No
                  FROM JobTitle AS J1
                  JOIN JobTitle AS J2
                    ON J1.BookingID = J2.BookingID
                 WHERE J1.JobTitleID >= J2.JobTitleID
                 GROUP BY J1.BookingID, J1.JobTitleID
                ) AS J3
          JOIN JobTitle AS J4
            ON J3.BookingID  = J4.BookingID
           AND J3.JobTitleID = J4.JobTitleID
          JOIN Booking  AS B
            ON B.BookingID = J4.BookingID
       ) AS J
  FULL OUTER JOIN
       (SELECT R4.*, R3.Rec_Seq_No
          FROM (SELECT R1.Receipt_No, R1.ID, COUNT(*) AS Rec_Seq_No
                  FROM First_Graphics_Debtors AS R1
                  JOIN First_Graphics_Debtors AS R2
                    ON R1.Receipt_No = R2.Receipt_No
                 WHERE R1.ID >= R2.ID
                 GROUP BY R1.Receipt_No, R1.ID
                ) AS R3
           JOIN First_Graphics_Debtors AS R4
             ON R3.Receipt_No = R4.Receipt_No
            AND R3.ID         = R4.ID
       ) AS R
    ON J.Receipt_No = R.Receipt_No AND J.Job_Seq_No = R.Rec_Seq_No
ORDER BY NVL(J.Receipt_No, R.Receipt_No), NVL(J.Job_Seq_No, R.Rec_Seq_No);

最终样本查询

最后将其嵌入到主查询中会给出(一个非常详细的版本)所需的结果:

SELECT B.*, JR.*
  FROM Booking AS B
  JOIN (SELECT NVL(J.Receipt_No, R.Receipt_No) AS Rec_No,
               NVL(J.Job_Seq_No, R.Rec_Seq_No) AS Seq_No,
               J.*, R.*
          FROM (SELECT B.Receipt_No, J4.*, J3.Job_Seq_No
                  FROM (SELECT J1.BookingID, J1.JobTitleID, COUNT(*) AS Job_Seq_No
                          FROM JobTitle AS J1
                          JOIN JobTitle AS J2
                            ON J1.BookingID = J2.BookingID
                         WHERE J1.JobTitleID >= J2.JobTitleID
                         GROUP BY J1.BookingID, J1.JobTitleID
                        ) AS J3
                  JOIN JobTitle AS J4
                    ON J3.BookingID  = J4.BookingID
                   AND J3.JobTitleID = J4.JobTitleID
                  JOIN Booking  AS B
                    ON B.BookingID = J4.BookingID
               ) AS J
          FULL OUTER JOIN
               (SELECT R4.*, R3.Rec_Seq_No
                  FROM (SELECT R1.Receipt_No, R1.ID, COUNT(*) AS Rec_Seq_No
                          FROM First_Graphics_Debtors AS R1
                          JOIN First_Graphics_Debtors AS R2
                            ON R1.Receipt_No = R2.Receipt_No
                         WHERE R1.ID >= R2.ID
                         GROUP BY R1.Receipt_No, R1.ID
                        ) AS R3
                   JOIN First_Graphics_Debtors AS R4
                     ON R3.Receipt_No = R4.Receipt_No
                    AND R3.ID         = R4.ID
               ) AS R
            ON J.Receipt_No = R.Receipt_No AND J.Job_Seq_No = R.Rec_Seq_No
       ) AS JR
    ON B.Receipt_No = JR.Rec_No
 WHERE B.Receipt_No = 753263343
 ORDER BY B.BookingID, Seq_No;

有一个非常有选择性的列列表:

SELECT B.BookingID    AS Booking,
       B.Receipt_No   AS Receipt,
       B.Client       AS Client,
       JR.JobTitleID  AS Title
       JR.JobTitle    AS JobTitle,
       JR.Old_Balance AS Old_Balance,
       JR.New_Balance AS New_Balance
  FROM Booking AS B
...

最终样本输出

我从样本数据中获得的结果数据是:

booking   receipt    client  title  jobtitle            old_balance new_balance
208       753263343  Chaka   460    A3 Full Colour      152161      0
208       753263343  Chaka   461    Flex Banner         152161      137637
208       753263343  Chaka   462    A2 Single Colour    152161      150161
208       753263343  Chaka                              152161      151161

唯一剩下的问题是MySQL是否支持FULL OUTER JOIN表示法。如果没有,您可以对此样本数据使用RIGHT OUTER JOIN(作业标题信息中的行数少于FGD信息中的行数。)


使用OLAP功能

更新:这是基于现在已知的错误查询。必须在此处进行类似的更改,以使其按要求运行。

使用OLAP函数,我认为您能够像这样创建排序结果集:

SELECT BookingID,
       ROW_NUMBER() OVER (PARTITION BY BookingID ORDER BY JobTitleID) AS Job_Seq_No
  FROM JobTitle;

SELECT Receipt_No,
       ROW_NUMBER() OVER (PARTITION BY Receipt_No ORDER BY ID) AS Rec_Seq_No
  FROM First_Graphics_Debtors;

但是,我对SQL的这一部分信心不足。但是,生成的大查询更简单:

SELECT B.*, J.*, R.*
  FROM Booking AS B
  LEFT JOIN (SELECT J1.*, J2.Job_Seq_No
               FROM (SELECT BookingID,
                            ROW_NUMBER()
                            OVER (PARTITION BY BookingID ORDER BY JobTitleID)
                            AS Job_Seq_No
                       FROM JobTitle
                    ) AS J2
               JOIN JobTitle AS J1 ON J2.BookingID = J1.BookingID
            ) AS J
    ON B.BookingID = J.BookingID
  LEFT JOIN (SELECT R1.*, R2.Rec_Seq_No
               FROM (SELECT Receipt_No,
                            ROW_NUMBER() OVER (PARTITION BY Receipt_No ORDER BY ID)
                            AS Rec_Seq_No
                       FROM First_Graphics_Debtors
                    ) AS R2
               JOIN First_Graphics_Debtors AS R1 ON R1.Receipt_No = R2.Receipt_No
            ) AS R
 WHERE J.Job_Seq_No = R.Rec_Seq_No
   AND B.Receipt_No = 753263343
 ORDER BY B.BookingID, COALESCE(J2.Job_Seq_No, R2.Rec_Seq_No);

警告:更多未经测试的SQL!