3

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

以下の列のデータは、recipient_noに関連する4つの行からデータを取得する代わりに、3回繰り返されます。

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

4

3 に答える 3

1

あなたの問題はあなたのGROUP BY条項によるものだと私はかなり確信しています。それを使用する目的がわからないが、それなしで試してください。行が重複する場合は、を使用してみてくださいSELECT DISTINCT。その列に基づいて結果を並べ替えることが目的の場合は、を使用しますORDER BY

また、句でreceipt_no2回指定するのWHEREは冗長です。これらの2つのテーブルはすでにその列で結合されているため、1つのテーブルでフィルタリングするだけで済みます。また、列名のスペースやコンマ、予約語と同じ名前の列など、いくつかの特別な例外を除いて、バッククォートは実際には必要ありません(他にもいくつかある場合があります)。バックティックが必要なように見える唯一の列は列ですが、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 に答える
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 に答える
0

Travesty3がテーブルエイリアスとバックティックについて言ったことに完全に同意します。

あなたの問題は、2つの別々のクエリであるはずのクエリを1つにまとめようとしていることだと思います。任意の予約について、任意の数の役職エントリを持つことができ、役職情報とは完全に独立して、任意の数のFirstGraphicsDebtorsエントリを持つことができます。サンプルの領収書753263343のサンプルデータには、1つの予約、3つの役職エントリ、および4つの最初のグラフィック債務者エントリがあります。

デフォルト(GROUP BY句なし)では、3セットの行(1 x 3 x 4)の外積に対応する12個のエントリを取得します。

MySQLのGROUPBYは、他のほとんどのDBMSとは異なります。標準SQLでは、GROUP BY句から非集計列を省略できません(すべての列が非集計です)。

あなたが求めているのは、次のような出力結果セットです(First Graphics Debtorsの略語としてFGDを使用):

+-------------------+---------------------+---------------+
| 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のセットです。

ただし、2つの別々のクエリを使用する方がよいでしょう。1つは役職情報を取得し、もう1つはFGD情報を取得します(2つのうち1つだけが予約情報を返す必要があります)。ただし、その後、アプリケーションコードでいくつかのプレゼンテーション作業を行う必要があります(ここでプレゼンテーション作業を行う必要がありますが、それは別の議論です)。

ですから、気の弱い人には、2つのクエリを使用することをお勧めします。勇敢な人のために、読んでください...


ブレイブのために

更新:TDQDまでの資料—テストを含めて軽度の誤りがあります。

まず最初に、それがあなたが求めているものである場合、それは可能ですが、それを行うのは比較的難しい作業です。次に、DBMSのOLAP関数を使用した単純なヒープです。MySQL(およびその他のDBMS)では、一時テーブルを使用して中間結果を保持できます。

予約IDで予約と役職に参加します。領収書番号で予約とFGDに参加します。2つの中間結果セットを作成するとします。

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);

はい、の使用*は怠惰です。これを改良して、本番クエリで必要な列の正確なリストを一覧表示します。デバッグの場合、すべてのデータが表示されることを確認します。これはおそらく役に立ちます。

2つの中間結果セットを作成するにはどうすればよいですか?

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;

同様に、SequenceedReceiptsの場合:

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!

更新: この警告は、ぼんやりとそこに置かれていませんでした。どんなに一生懸命頑張っても、最初は複雑なクエリを正確に書くことができないと思います。また、以前に示したアウトライン結果を作成しようとはしなかったので(私は常に2つの別々のクエリを使用し、代わりにプレゼンテーションツールアプローチでデータを結合しました)、間違いは避けられなかったと思います。

TDQD —テストを含む

実際の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;

これらの2つの結果は、それぞれ対応するテーブルと結合できますが、結合条件は私が最初に書いたものとは異なります。

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);

残念ながら、サンプルデータには3行しか生成されません。4つのレシート番号の最後を省略します。これが私がTDQDを行う理由です。近道をすると問題があります。

最後のクエリの構造は、JサブクエリとRサブクエリが(一般に)FULL OUTER JOINを使用して結合されるようにする必要があります。したがって、共通のレシート番号または予約IDのいずれかが必要です。JobTitle情報に領収書番号を追加することにしました。FirstGraphicsDebtors情報に追加された予約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;

次に、2つのシーケンスされたリストを完全な外部結合と組み合わせます。

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がFULLOUTERJOIN表記をサポートしているかどうかです。そうでない場合は、このサンプルデータで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 に答える