0

まず第一に、これは単なるテストテーブルです。いくつかのSQLクエリを学びたいと思います。'peter'と同じ頻度で(ミュンヘンで始まる)同じフライトを予約したのは誰か知りたいです。正しい結果が得られるクエリは次のとおりです。

SELECT r1.vorname
FROM (
SELECT p1.vorname, count(p1.passnr) as anzahl
FROM passagier p1, teilnehmer t1, abflug a
WHERE a.abflug = 'münchen'
AND t1.flugnr = a.flugnr
AND t1.passnr = p1.passnr
group by p1.passnr ) as r1,
(
SELECT p1.vorname, count(p1.passnr) as anzahl
FROM passagier p1, teilnehmer t1, abflug a
WHERE a.abflug = 'münchen'
AND t1.flugnr = a.flugnr
AND t1.passnr = p1.passnr
group by p1.passnr ) as r2

WHERE r2.vorname = 'peter'
AND r1.vorname != 'peter'
AND r1.anzahl = r2.anzahl

同じ結果を得るためのより良いクエリはありますか?

--
-- Table structure for table `abflug`
--

CREATE TABLE IF NOT EXISTS `abflug` (
  `flugnr` varchar(30) NOT NULL,
  `zielkrz` varchar(30) NOT NULL,
  `ziel` varchar(30) NOT NULL,
  `abflkrz` varchar(30) NOT NULL,
  `abflug` varchar(30) NOT NULL,
  PRIMARY KEY (`flugnr`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `abflug`
--

INSERT INTO `abflug` (`flugnr`, `zielkrz`, `ziel`, `abflkrz`, `abflug`) VALUES
('ba921', 'fra', 'frankfurt', 'muc', 'münchen'),
('lh807', 'nrt', 'tokyo narita', 'fra', 'frankfurt'),
('lh808', 'fra', 'frankfurt', 'kix', 'osaka kansai'),
('lh809', 'kix', 'osaka kansai', 'fra', 'frankfurt');


--
-- Table structure for table `passagier`
--

CREATE TABLE IF NOT EXISTS `passagier` (
  `passnr` varchar(30) NOT NULL,
  `vorname` varchar(30) NOT NULL,
  `name` varchar(30) NOT NULL,
  PRIMARY KEY (`passnr`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `passagier`
--

INSERT INTO `passagier` (`passnr`, `vorname`, `name`) VALUES
('10118', 'gerhard', 'schröder'),
('10120', 'peter', 'müller'),
('10123', 'angela', 'merkel'),
('10999', 'aryan', 'layes'),
('11000', 'jessica', 'alba');

--
-- Table structure for table `teilnehmer`
--

CREATE TABLE IF NOT EXISTS `teilnehmer` (
  `flugnr` varchar(30) NOT NULL,
  `passnr` varchar(30) NOT NULL,
  `datum` varchar(30) NOT NULL,
  PRIMARY KEY (`flugnr`,`passnr`,`datum`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `teilnehmer`
--

INSERT INTO `teilnehmer` (`flugnr`, `passnr`, `datum`) VALUES
('ba921', '10120', '20.1.2012'),
('ba921', '10120', '23.1.2012'),
('ba921', '10123', '20.1.2012'),
('ba921', '10999', '20.1.2012'),
('ba921', '10999', '23.1.2012'),
('ba921', '11000', '23.1.2012'),
('lh807', '10118', '20.1.2012'),
('lh807', '10120', '20.1.2012'),
('lh807', '10123', '20.1.2012'),
('lh808', '10118', '27.3.2012'),
('lh808', '10120', '23.1.2012'),
('lh808', '10123', '23.1.2012'),
('lh809', '10120', '23.1.2012');
4

1 に答える 1

0

おそらくもっと効率的な方法があります。次のクエリは、サブクエリで Peter の情報を計算し、それを残りのクエリに結合します。

select allp.*
from (SELECT p.passnr, count(p1.passnr) as anzahl
      FROM passagier p join
           teilnehmer t
           on t.passnr = p.passnr join
           abflug a
           on t.flugnr = a.flugnr
      where a.abflug = 'münchen'
      group by p.passnr
     ) allp cross join
     (SELECT count(p1.passnr) as anzahl
      FROM passagier p join
           teilnehmer t
           on t.passnr = p.passnr join
           abflug a
           on t.flugnr = a.flugnr 
      where a.abflug = 'münchen' AND
            p.vorname = 'peter'
      limit 1
     ) peter
where allp.forname <> 'peter' and allp.anzahl >= peter.anzahl

「制限」の使用は、データに複数のピーターがいる場合に備えています。

「with」ステートメントを使用してこれを簡素化することもできます。

with allp as (
      SELECT count(p1.passnr) as anzahl
      FROM passagier p join
           teilnehmer t
           on t.passnr = p.passnr join
           abflug a
           on t.flugnr = a.flugnr 
      where a.abflug = 'münchen'
     ) allp 
select *
from allp
where allp.forname <> 'peter' and
      allp.anzahl >= (select anzahl from allp where vorname = 'peter' limit 1)

このバージョンでは、すべてのデータを乗客ごとにまとめています。次に、「anzahl」が Peter のものよりも大きいものを選択します。mysql では、WHERE 句のサブクエリが (おそらく) すべての行で評価されるため、最初のバージョンのパフォーマンスが向上する可能性があります。

于 2012-08-08T13:42:02.843 に答える