有人接受 SQL 挑战吗?因为到目前为止我所有的努力都不足以简化问题并将其放入问题中......
就这样吧。在下面的示例中,我们需要包括:
- 所有付费航类
- 飞往某个国家/地区的航类(付费或免费)(如果某人已搭乘另一趟航类飞往该国家/地区的付费城市)
这已经很棘手了,但还有更多的事情要做。
- 如果某人飞往一个无需入场费的城市,但该城市位于 确实收费的国家/地区,该航类仍被视为已付费 并且也必须包含在内。
编辑: 我添加了 110 航类,这应该有助于揭示不必要添加的免费航类。
下面是 SQL 查询应产生的结果集:
+--------------------------------------------------------------+
| Desired result set |
+--------------------------------------------------------------+
| FlightNumber | ID | Name | LocationID | location.Name |
+--------------------------------------------------------------+
| 102 | 2 | Tom | 500 | NL - NoFee | -> because Tom has a paid flight to Amsterdam
| 103 | 2 | Tom | 501 | Amsterdam (NL) - Fee | -> because Amsterdam is a paid location
| 105 | 4 | Bob | 501 | Amsterdam (NL) - Fee | -> because Amsterdam is a paid location
| 107 | 6 | Bill | 503 | ITA - Fee | -> because ITA is a paid location
| 108 | 7 | Ryan | 503 | ITA - Fee | -> because ITA is a paid location
| 109 | 7 | Ryan | 505 | Venice (ITA) - NoFee | -> because Venice is located inside ITA
+--------------------------------------------------------------+
有谁知道如何使用 SQL 获得这个甜蜜的结果集?
一个好的起点:
SELECT flights.FlightNumber, people.ID, people.Name, flights.LocationID, locations.Name
FROM flights
INNER JOIN people ON (people.ID = flights.ID)
INNER JOIN locations ON (locations.LocationID = flights.LocationID)
创建/插入
CREATE TABLE `people` (
`ID` INT NOT NULL,
`Name` VARCHAR(45) NULL,
PRIMARY KEY (`ID`) );
CREATE TABLE `locations` (
`LocationID` INT NOT NULL,
`Name` VARCHAR(45) NULL,
`EntryFee` TINYINT(1) NULL,
`ParentLocationID` INT NULL,
PRIMARY KEY (`LocationID`) );
CREATE TABLE `flights` (
`FlightNumber` INT NOT NULL,
`ID` INT NULL,
`LocationID` INT NULL,
PRIMARY KEY (`FlightNumber`) ,
INDEX `fk_purchases_buyers_idx` (`LocationID` ASC) ,
INDEX `fk_flights_people1_idx` (`ID` ASC) ,
CONSTRAINT `fk_purchases_buyers`
FOREIGN KEY (`LocationID`)
REFERENCES `locations` (`LocationID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_flights_people1`
FOREIGN KEY (`ID`)
REFERENCES `people` (`ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION);
INSERT INTO `people` (`ID`, `Name`) VALUES
(1, 'John'),
(2, 'Tom'),
(3, 'Kate'),
(4, 'Bob'),
(5, 'Mike'),
(6, 'Bill'),
(7, 'Ryan');
INSERT INTO `locations` (`LocationID`, `Name`, `EntryFee`, `ParentLocationID`) VALUES
(500, 'NL - NoFee', 0, NULL),
(501, 'Amsterdam (NL) - Fee', 1, 500),
(502, 'Rotterdam (NL) - NoFee', 0, 500),
(503, 'ITA - Fee', 1, NULL),
(504, 'Rome (ITA) - Fee', 1, 503),
(505, 'Venice (ITA) - NoFee', 0, 503);
INSERT INTO `flights` VALUES
(100, 1, 500),
(101, 1, 502),
(102, 2, 500),
(103, 2, 501),
(104, 3, 500),
(105, 4, 501),
(106, 5, 502),
(107, 6, 503),
(108, 7, 503),
(109, 7, 505),
(110, 6, 502);
不重要的说明:我知道这个例子在将国家和城市存储在同一个表中以及拥有飞往一个国家和一个城市的航类记录的意义上并不完全符合逻辑。但这只是一个例子。至少它比 t1.col1
之类的东西更具可读性。
最佳答案
以下应该有效:
SELECT F.FlightNumber, P.ID, P.Name, F.LocationID, LOC.Name AS Loc_Name
FROM flights F
INNER JOIN people P ON P.ID = F.ID
INNER JOIN (SELECT L1.LocationID, L1.`Name`, L1.`ParentLocationID`
FROM locations L1
LEFT JOIN locations L2 ON L1.`ParentLocationID` = L2.LocationID
WHERE L1.`EntryFee` = 1 OR L2.`EntryFee` = 1) AS LOC ON LOC.LocationID = F.LocationID
UNION
SELECT F.FlightNumber, PAID_FL.ID, PAID_FL.Name, F.LocationID, PAID_FL.Loc_Name
FROM flights F
INNER JOIN (SELECT F.FlightNumber, P.ID, P.Name, LOC.Name AS Loc_Name,LOC.`ParentLocationID` AS LocationID
FROM flights F
INNER JOIN people P ON P.ID = F.ID
INNER JOIN (SELECT L1.LocationID, L1.`ParentLocationID`, L2.`Name`
FROM locations L1
LEFT JOIN locations L2 ON L1.`ParentLocationID` = L2.LocationID
WHERE L1.`EntryFee` = 1 OR L2.`EntryFee` = 1) AS LOC ON LOC.LocationID = F.LocationID) PAID_FL ON F.ID = PAID_FL.ID AND F.LocationID = PAID_FL.LocationID
关于mysql - 通过交叉引用和自引用从多个表中进行选择[脑力破解者],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41448757/