3

三张表的结构。

预订

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

职称

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

职称

+------------+---------------------------+----------+--------+-----------+-----------+
| 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_paid图片new_balance

4

3 回答 3

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

于 2012-05-19T02:45:33.510 回答
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
于 2012-05-18T13:07:09.643 回答
0

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

我认为,您的问题是,您正试图将“应该”是两个单独的查询合并为一个。对于任何给定的预订,您可以拥有任意数量的职位名称条目,并且完全独立于职位名称信息,您可以拥有任意数量的 First Graphics Debtors 条目。在示例 Receipt 753263343 的示例数据中,您有一个 Booking、三个 Job Title 条目和 4 个 First Graphic Debtors 条目。

默认情况下(没有 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),您可以使用临时表来保存中间结果。

您在 Booking ID 上加入 Booking 和 Job Title。您在 Receipt No 上加入 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!

更新: 这个警告并不是随便放在那里的。无论我多么努力,我都不相信自己第一次就能准确地编写复杂的查询。而且我没有尝试生成我之前展示的大纲结果(我一直使用两个单独的查询并在演示工具方法中组合数据),所以我认为错误是不可避免的。

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;

这两个结果可以分别和对应的表join回来,但是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
 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的原因;当我走捷径时,我发现有问题。

最后一个查询的结构需要使 J 和 R 子查询使用 FULL OUTER JOIN(通常)连接,因此它们需要共同的收据编号或预订 ID。我选择将 Receipt Number 添加到 JobTitle 信息中;添加到第一图形债务人信息中的预订 ID 可以正常工作;对称性建议两者都做,但这也可能被认为是矫枉过正。

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!

于 2012-05-18T19:22:36.293 回答