mysql - 通过交叉引用和自引用从多个表中进行选择[脑力破解者]

标签 mysql sql

有人接受 SQL 挑战吗?因为到目前为止我所有的努力都不足以简化问题并将其放入问题中......

就这样吧。在下面的示例中,我们需要包括:

  • 所有付费航类
  • 飞往某个国家/地区的航类(付费或免费)(如果某人已搭乘另一趟航类飞往该国家/地区的付费城市)

这已经很棘手了,但还有更多的事情要做。

  • 如果某人飞往一个无需入场费的城市,但该城市位于 确实收费的国家/地区,该航类仍被视为已付费 并且也必须包含在内。

enter image description here 编辑: 我添加了 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/

相关文章:

sql - 将带有图像的 Excel 数据导入 SQL Server

mysql - 'like' 内的 SQL 'exists' 条件

MySQL:如果 meta_key 不存在则返回帖子

MYSQL import : port a big list of names into mysql table column. 一个简单的方法?

mysql - logrotate后不写入MariaDB慢日志

mysql - 什么情况下外键不能为空?

mysql - MySQL 是否支持部分索引?

sql - 列名中应该使用下划线吗?

Linux 上的 php 和 mysql 安装

mysql - 如何在 Sequelize 模型中动态选择数据库(或 "schema")?