I totally agree that Travesty3 talks about table aliases and backlinks.
, , , , . , . Receipt 753263343 , 4 .
( GROUP BY) 12 , (1 x 3 x 4).
GROUP BY MySQL ; SQL GROUP BY ( ).
, , ( 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.
, , , , FGD ( ). , ( , ).
, , . , ...
: TDQD — , .
, : , , , . -, OLAP . MySQL ( ) .
. FGD . , :
SequencedJobTitles(Booking ID, Job_Seq_No)
SequencedReceipts(Receipt No, Rec_Seq_No)
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;
, . , , . , ; TDQD (Test Driven Query Design).
, :
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;
, , :
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);
, ; . TDQD; , , .
, J R FULL OUTER JOIN ( ), , . JobTitle; , 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. , (, , 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!