私は次のクエリ (およびそれに類似した他のクエリ) と格闘してきましたが、何かが足りないか、間違ったタイプのデータベースまたは何かを使用しているように感じます。
このクエリを使用して、過去 10 年間に英国と特定の都市で、年間の新しい映画の総数と上映が中止された (閉鎖された) 映画の総数を取得します。クエリは、何年にもわたって多くの町や郡に対しても実行されます。
他のクエリも同様のことを行い、UNION ALL
オープニングまたはクロージングの記録年を取得するクエリの最後に a を追加することがあります。
年次データの代わりに月次データと四半期データに対して実行されるクエリもあり、特定の四半期 (例: 第 3 四半期) または月 (例: 3 月) の過去のオープン/クローズを比較するだけのクエリもあります。
2012 年の英国とロンドンを比較するクエリは次のとおりです。
SELECT inc.opening_year as year, inc.number_of_films as opens,
diss.number_of_films as closures, inc.uk_films as uk_opens,
diss.uk_films as uk_closures
FROM
(SELECT film_db.opening_year, uk.number_of_films as uk_films,
COUNT(film_db.id_film_db) as number_of_films
FROM film_db
JOIN postcodes ON id_postcodes = opening_postcode_id
JOIN towns ON id_towns = town_id AND town = 'London'
JOIN (SELECT opening_year, COUNT(film_db.id_film_db) as number_of_films
FROM film_db
WHERE opening_year <= 2012 AND opening_year >= (2012 - 10)
GROUP BY opening_year
) uk ON uk.opening_year = film_db.opening_year
WHERE film_db.opening_year <= 2012 AND film_db.opening_year >= (2012 - 10)
GROUP BY film_db.opening_year
ORDER BY film_db.opening_year DESC
) inc
JOIN
(SELECT film_db.closing_year, uk.number_of_films as uk_films,
COUNT(film_db.id_film_db) as number_of_films
FROM film_db
JOIN postcodes ON id_postcodes = postcode_id
JOIN towns ON id_towns = town_id AND town = 'London'
JOIN (SELECT closing_year, COUNT(film_db.id_film_db) as number_of_films
FROM film_db
WHERE film_db.closing_year <= 2012 AND film_db.closing_year >= (2012 - 10)
GROUP BY film_db.closing_year
) uk ON uk.closing_year = film_db.closing_year
WHERE film_db.closing_year <= 2012 AND film_db.closing_year >= (2012 - 10)
GROUP BY film_db.closing_year
ORDER BY film_db.closing_year DESC
) diss ON diss.closing_year = inc.opening_year
デシベルのSHOW CREATE TABLE
出力は次のとおりです。
フィルム データベース:
CREATE TABLE `film_db` (
`id_film_db` int(11) NOT NULL AUTO_INCREMENT,
`film_name` varchar(255) DEFAULT NULL,
`category` varchar(100) DEFAULT NULL,
`status` varchar(50) DEFAULT NULL,
`opening_date` date DEFAULT NULL,
`opening_year` int(4) DEFAULT NULL,
`opening_month` int(2) DEFAULT NULL,
`opening_quarter` int(1) DEFAULT NULL,
`closing_date` date DEFAULT NULL,
`closing_year` int(4) DEFAULT NULL,
`closing_month` int(2) DEFAULT NULL,
`closing_quarter` int(1) DEFAULT NULL,
`datetime` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`postcode_id` int(4) NOT NULL DEFAULT '0',
`opening_postcode_id` int(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id_film_db`),
KEY `opening_date` (`opening_date`),
KEY `status` (`status`),
KEY `postcode_id` (`postcode_id`),
KEY `type` (`category`),
KEY `opening_year` (`opening_year`),
KEY `opening_month` (`opening_month`,`opening_year`) USING BTREE,
KEY `opening_quarter` (`opening_quarter`,`opening_year`) USING BTREE,
KEY `closing_year` (`closing_year`),
KEY `closing_month` (`closing_year`,`closing_month`),
KEY `closing_quarter` (`closing_year`,`closing_quarter`),
KEY `closing_date` (`closing_date`),
KEY `opening_closing_date` (`opening_date`,`closing_date`),
KEY `opening_postcode` (`opening_postcode_id`),
FULLTEXT KEY `film_name` (`film_name`)
) ENGINE=MyISAM AUTO_INCREMENT=10649173 DEFAULT CHARSET=utf8
郵便番号:
CREATE TABLE `postcodes` (
`id_postcodes` int(4) NOT NULL AUTO_INCREMENT,
`postcode` varchar(9) NOT NULL,
`town_id` int(4) NOT NULL,
`lat` float NOT NULL,
`lng` float NOT NULL,
PRIMARY KEY (`id_postcodes`),
UNIQUE KEY `postcode` (`postcode`) USING BTREE,
KEY `town` (`town_id`)
) ENGINE=MyISAM AUTO_INCREMENT=5705 DEFAULT CHARSET=latin1
町:
CREATE TABLE `towns` (
`id_towns` int(4) NOT NULL AUTO_INCREMENT,
`town` varchar(150) NOT NULL,
`county_id` int(3) NOT NULL,
PRIMARY KEY (`id_towns`),
KEY `county` (`county_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1606 DEFAULT CHARSET=latin1
EXPLAIN EXTENDED
出力は次のとおりです。
1 PRIMARY <derived2> ALL 11 100
1 PRIMARY <derived4> ALL 11 100 Using where; Using join buffer
4 DERIVED <derived5> ALL 11 100 Using where; Using temporary; Using filesort
4 DERIVED film_db ref postcode_id,closing_year,closing_month,closing_quarter closing_year 5 uk.closing_year 2 100 Using where
4 DERIVED postcodes eq_ref PRIMARY,town PRIMARY 4 film_db.postcode_id 1 100
4 DERIVED towns eq_ref PRIMARY PRIMARY 4 postcodes.town_id 1 100 Using where
5 DERIVED film_db ALL closing_year,closing_month,closing_quarter 9895680 47.66 Using where; Using temporary; Using filesort
2 DERIVED <derived3> ALL 11 100 Using where; Using temporary; Using filesort
2 DERIVED film_db ref opening_year,opening_postcode opening_year 5 uk.opening_year 3 100 Using where
2 DERIVED postcodes eq_ref PRIMARY,town PRIMARY 4 film_db.opening_postcode_id 1 100
2 DERIVED towns eq_ref PRIMARY PRIMARY 4 postcodes.town_id 1 100 Using where
3 DERIVED film_db ALL opening_year 9895680 54.53 Using where; Using temporary; Using filesort
ご覧のとおり、MySQL は、film_db
テーブルでのフィルタリングによってパフォーマンスに違いが生じるとは考えていないため、キーを使用しません。
そう:
インデックスをより適切に使用するために、このクエリを改善できますか?
クエリがより高速に実行されるように、インデックス作成を改善できますか?
複雑な条件と結合を持つエントリの数をカウントすることに主に関心があるこの種のクエリの代わりに使用する必要がある別のデータベース タイプ (MySQL ではない) はありますか?