Выберите один отдельный столбец, другие могут быть неотличимыми.- MySQL
-
26-09-2019 - |
Вопрос
Хорошо, у меня есть временная таблица с 135 000 строк, я пытаюсь вставить некоторые значения из этой временной таблицы в другие таблицы.
Это схема, которую я использую
телевизорсоблазнительный
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| PROGTITLE | text | YES | | NULL | |
| SUBTITLE | text | YES | | NULL | |
| EPISODE | text | YES | | NULL | |
| YR | year(4) | YES | | NULL | |
| DIRECTOR | text | YES | | NULL | |
| PERFORMERS | text | YES | | NULL | |
| PREMIERE | tinyint(1) | YES | | NULL | |
| FILM | tinyint(1) | YES | | NULL | |
| RPEAT | tinyint(1) | YES | | NULL | |
| SUBTITLES | tinyint(1) | YES | | NULL | |
| WIDESCREEN | tinyint(1) | YES | | NULL | |
| NEWSERIES | tinyint(1) | YES | | NULL | |
| DEAFSIGNED | tinyint(1) | YES | | NULL | |
| BNW | tinyint(1) | YES | | NULL | |
| STARRATING | tinyint(4) | YES | | NULL | |
| CERTIFICATE | varchar(5) | YES | | NULL | |
| GENRE | varchar(50) | YES | | NULL | |
| DESCRIPTION | text | YES | | NULL | |
| CHOICE | tinyint(1) | YES | | NULL | |
| PROGDATE | date | YES | | NULL | |
| STARTIME | time | YES | | NULL | |
| ENDTIME | time | YES | | NULL | |
| DURATION | int(11) | YES | | NULL | |
| CHANNELID | int(11) | NO | | NULL | |
+-------------+-------------+------+-----+---------+-------+
каналы
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| CHANNELID | int(11) | NO | PRI | NULL | auto_increment |
| CHANNELNAME | varchar(50) | YES | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
жанр
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| GENREID | int(11) | NO | PRI | NULL | auto_increment |
| GENRENAME | varchar(50) | YES | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
программа
+-------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------+------+-----+---------+----------------+
| PROGRAMMEID | int(11) | NO | PRI | NULL | auto_increment |
| GENREID | int(11) | NO | MUL | NULL | |
| PROGTITLE | text | YES | | NULL | |
| YR | year(4) | YES | | NULL | |
| DIRECTOR | text | YES | | NULL | |
| PERFORMERS | text | YES | | NULL | |
| FILM | tinyint(1) | YES | | NULL | |
| WIDESCREEN | tinyint(1) | YES | | NULL | |
| BNW | tinyint(1) | YES | | NULL | |
| CERTIFICATE | varchar(5) | YES | | NULL | |
| DESCRIPTION | text | YES | | NULL | |
+-------------+------------+------+-----+---------+----------------+
эпизод
+-------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+----------------+
| EPISODEID | int(11) | NO | PRI | NULL | auto_increment |
| PROGRAMMEID | int(11) | NO | MUL | NULL | |
| SUBTITLE | text | YES | | NULL | |
| EPISODE | text | YES | | NULL | |
| DIRECTOR | text | YES | | NULL | |
| PERFORMERS | text | YES | | NULL | |
| DESCRIPTION | text | YES | | NULL | |
+-------------+---------+------+-----+---------+----------------+
программа канала
+--------------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+------------+------+-----+---------+----------------+
| CHANNELPROGRAMMEID | int(11) | NO | PRI | NULL | auto_increment |
| CHANNELID | int(11) | NO | MUL | NULL | |
| PROGRAMMEID | int(11) | NO | MUL | NULL | |
| EPISODEID | int(11) | NO | MUL | NULL | |
| RPEAT | tinyint(1) | YES | | NULL | |
| NEWSERIES | tinyint(1) | YES | | NULL | |
| PREMIERE | tinyint(1) | YES | | NULL | |
| CHOICE | tinyint(1) | YES | | NULL | |
| SUBTITLES | tinyint(1) | YES | | NULL | |
| DEAFSIGNED | tinyint(1) | YES | | NULL | |
| STARRATING | tinyint(4) | YES | | NULL | |
| PROGDATE | date | YES | | NULL | |
| STARTTIME | time | YES | | NULL | |
| ENDTIME | time | YES | | NULL | |
| DURATION | tinyint(4) | YES | | NULL | |
+--------------------+------------+------+-----+---------+----------------+
Итак, немного предыстории: база данных представляет собой базу данных телепрограмм, таблица каналов и программ содержит все записи для каждого шоу на каждом канале, таблица программ содержит уникальные записи для каждой программы, эпизод содержит уникальные записи для каждого эпизода программ, которые имеют эпизоды
Я думаю, что моя путаница заключается в том, что я хочу выбрать отдельные заголовки программ из временной таблицы, чтобы заполнить таблицу программ, но мне нужна другая информация, связанная с ней.
Например, если бы я сделал
select distinct(progtitle) from tvtemptable;
Это вернет мне только значение столбца заголовка программы, тогда как на самом деле мне нужен заголовок программы и некоторые другие данные.
Итак, если я попытаюсь выбрать больше информации вот так
mysql> select distinct progtitle, yr, director, film from tvtemptable
limit 30;
+-----------------------------------+------+---------------------+------+
| progtitle | yr | director | film |
+-----------------------------------+------+---------------------+------+
| Teleshopping | 2000 | | 0 |
| Cinemania | 2000 | | 0 |
| Whose Line Is It Anyway? | 2000 | | 0 |
| Just Desserts | 2004 | Kevin Connor | 1 |
| Law & Order | 2000 | Matthew Penn | 0 |
| Jane Doe: Yes, I Remember it Well | 2006 | Armand Mastroianni | 0 |
| CSI: NY | 2000 | David Jackson | 0 |
| CSI: Crime Scene Investigation | 2000 | Kenneth Fink | 0 |
| NCIS | 2000 | Colin Bucksey | 0 |
| CSI: Miami | 2000 | | 0 |
| Enter the Dragon | 1973 | Robert Clouse | 1 |
| Close | 2000 | | 0 |
| My Son Is Innocent | 1996 | Larry Elikann | 1 |
| Law & Order | 2000 | Christopher Misiano | 0 |
| Murder 101 | 2006 | Christian I Nyby II | 1 |
| CSI: NY | 2000 | Christine Moore | 0 |
| CSI: Crime Scene Investigation | 2000 | Bill Eagles | 0 |
| Rush Hour | 1998 | Brett Ratner | 1 |
| Dark Blue | 2000 | Jeffrey Hunt | 0 |
| CSI: Crime Scene Investigation | 2000 | Richard J Lewis | 0 |
| Ordinary Miracles | 2005 | Michael Switzer | 1 |
| Law & Order | 2000 | Jace Alexander | 0 |
| Wounded Heart | 1995 | Vic Sarin | 1 |
| CSI: NY | 2000 | Jonathan Glassner | 0 |
| Dark Blue | 2000 | Nathan Hope | 0 |
| Blade: The Series | 2000 | Michael Robison | 0 |
| K-Ville | 2000 | Kevin Dowling | 0 |
| Law & Order | 2000 | Jim Ellis | 0 |
| Reasons of the Heart | 1996 | Rick Jacobson | 1 |
| CSI: NY | 2000 | Anthony Hemingway | 0 |
+-----------------------------------+------+---------------------+------+
В столбце названия программы будет несколько дубликатов.Программы не повторяются для каждого нового режиссера, для некоторых программ указаны разные режиссеры, потому что в этих программах есть эпизоды.
Теперь мне удалось заставить выбор работать правильно. Например, если мне нужен только один дополнительный столбец
select distinct
t1.progtitle,
(select
t2.director
from
tvtemptable t2
where
t1.progtitle = t2.progtitle
limit 1) as "Director"
from
tvtemptable t1 limit 10;
+-----------------------------------+--------------------+
| progtitle | Director |
+-----------------------------------+--------------------+
| Teleshopping | |
| Cinemania | |
| Whose Line Is It Anyway? | |
| Just Desserts | Kevin Connor |
| Law & Order | Matthew Penn |
| Jane Doe: Yes, I Remember it Well | Armand Mastroianni |
| CSI: NY | David Jackson |
| CSI: Crime Scene Investigation | Kenneth Fink |
| NCIS | Colin Bucksey |
| CSI: Miami | |
+-----------------------------------+--------------------+
Очевидно, это будет беспорядочно, если я захочу выбрать более одного дополнительного столбца.
Так как же лучше всего это сделать?
Это моя команда вставки для заполнения таблицы программы из временной таблицы, в настоящее время она имеет ту же проблему с дубликатами в примере выбора, который я привел выше.
INSERT INTO PROGRAMME (
PROGTITLE, GENREID, YR, DIRECTOR,
PERFORMERS, FILM, WIDESCREEN, BNW,
CERTIFICATE, DESCRIPTION)
SELECT DISTINCT
T.PROGTITLE, G.GENREID, T.YR, T.DIRECTOR,
T.PERFORMERS, T.FILM, T.WIDESCREEN, T.BNW,
T.CERTIFICATE, T.DESCRIPTION
FROM
TVTEMPTABLE T
INNER JOIN GENRE G ON G.GENRENAME=T.GENRE
LEFT JOIN PROGRAMME P ON P.PROGTITLE=T.PROGTITLE
WHERE
P.PROGTITLE IS NULL
Решение
Прав ли я, полагая, что ваш TVTEMPTABLE
является результатом объединения таблиц откуда-то?
В этом случае, я думаю, вам будет проще работать в целом, если вы сначала разделите эту временную таблицу на несколько временных таблиц, имеющих тот же формат, что и ваши целевые таблицы.
Например (и я не знаю ваших данных, поэтому просто предполагаю):
-- All genres (matches your existing genres table)
create table genres_temp as
select distinct genre
from tvtemptable;
-- All programmes (matches your existing programme table)
create table programmes_temp as
select distinct all_the_programme_columns
from tvtemptable;
-- Contains the many-to-many relationship between genres and programmes
create table programme_genre_temp as
select distinct genre, progtitle
from tvtemptable;
Вышеупомянутое не отвечает на ваш вопрос, но может дать вам некоторые идеи, которые устранят проблему, заключающуюся в том, что информация о программе повторяется для каждого что-нибудь.Вам нужно выяснить, что это такое.
ОбновленоТо есть каждая программа повторяется один раз для каждого режиссера?Тогда мой вышеописанный подход имеет еще больше смысла:Сначала извлеките сущности и отношения.
Обновлено 2Хм, вы насильно вписываете режиссёра в программу, когда режиссёр имеет отношение к эпизоду?Кажется, это было бы ошибкой моделирования.В любом случае, если вас не волнует, какого режиссера вы выберете, вы можете сгруппироваться по progtitle
и использовать MAX()
вокруг всех остальных столбцов.Это даст вам отдельные названия программ и одно из значений для остальных столбцов.
SELECT T.PROGTITLE, max(G.GENREID), max(T.YR), max(T.DIRECTOR), etc
FROM TVTEMPTABLE T
INNER JOIN GENRE G ON G.GENRENAME=T.GENRE
LEFT JOIN PROGRAMME P ON P.PROGTITLE=T.PROGTITLE
WHERE P.PROGTITLE IS NULL
group by T.PROGTITLE;
Другие советы
Это не имеет смысла.Как строка может быть частично различимой и частично неразличимой?Думайте о выбранном результате как о таблице: как бы вы представили данные, если бы для PROGTITLE
который имеет несколько значений для остальных столбцов?
Это не ответ на ваш вопрос, но, вероятно, ответит на него для людей, которые ищут здесь:
В Postgresql это можно сделать с помощью SELECT DISTINCT ON, например:
SELECT DISTINCT ON (p.progtitle) p.* FROM progtitle p;
Я не знаю эквивалента MySQL.
Insert into xx (a,b)
Select a.ab, b.bb from (
Select distinct ab from a) a, (select distinct bb from b) b
Я читаю, что вам нужен список отдельных программ, но с некоторыми связанными данными в других столбцах для контекста?Вы можете сделать это с помощью номеров строк.
select * from
(select *,
row_number() over (partition by progtitle order by year desc) N
from tvtempta) t
where t.N = 1
Еще лучше, вы можете использовать order by
предложение, чтобы указать самый последний, первый или какой-либо другой предпочтительный способ выбора нужной строки.Это синтаксис T-SQL, и я думаю, что тот же синтаксис должен работать в Oracle (если нет, то это определенно возможно в Oracle).К сожалению, я не знаю, сможете ли вы сделать это в MySQL.