Справка по запросу; нужен ли мне подзапрос?

#mysql #drupal-6

#mysql #drupal-6

Вопрос:

(Уже опубликовано на drupal.stackexchange.com без ответа; поскольку вопрос специфичен для mysql, надеюсь, кто-нибудь здесь сможет помочь …)

Я унаследовал этот код, который выполняется на нашей домашней странице. Он используется для пользовательского отображения определенных фрагментов связанной информации. Вот как все настроено:

У нас есть статья. В нем есть ряд полей ссылок на узлы, которые позволяют нам связывать связанные изображения (фактически сами узлы, которые содержат снимок головы и некоторый текст; это не фактическое прикрепленное изображение.) У каждого из этих заголовков есть миниатюра, созданная с помощью ImageCache, чтобы мы могли отображать уменьшенную версию в результатах поиска и на страницах типа списка.

У нас есть новое требование, согласно которому, если связанный узел изображения для конкретной статьи имеет связанный с ним определенный термин таксономии (tid), он должен отображаться иначе, чем другие изображения.

Существующий запрос (который я не писал) выглядит следующим образом:

 SELECT DISTINCT n.title, nr.teaser, n.nid, DATE_FORMAT(FROM_UNIXTIME(n.created), '%M %e, %Y') AS date, f.filepath AS image, cfri.field_related_images_nid as image_id 

FROM node n JOIN node_revisions nr ON n.nid = nr.nid 
LEFT JOIN content_field_related_images cfri ON (n.nid = cfri.nid AND cfri.delta = 0) 
LEFT JOIN content_field_att_file cfaf ON cfri.field_related_images_nid = cfaf.nid 
LEFT JOIN files f ON cfaf.field_att_file_fid = f.fid  
JOIN term_node tn2 ON n.nid = tn2.nid 

WHERE n.status = 1 
AND n.type = 'article'   
AND nr.body LIKE '%kimberly-clark%' 
AND tn2.tid = 143 
ORDER BY n.created DESC LIMIT 3
  

Это возвращает набор записей, который выглядит следующим образом:

 TITLE         |  TEASER           |  NID |  DATE            |  IMAGE                            | IMAGE_ID
==========================================================================================================
Exec Profile  |  Could you please | 67491 | April 29, 2011  | sites/default/files/kcjones.jpg   | 67572
Unilver Ads   |  Unilever topped  | 67421 | April 20, 2011  | sites/default/files/unilever.jpg  | 66889
  

Это все хорошо. Но что мне нужно сделать, так это (каким-то образом в том же запросе) также вернуть tid, который идет с image_id из таблицы term_node. Сам по себе для одного узла изображения этот запрос прост:

 SELECT tid FROM term_node WHERE nid = 67572
  

Но как мне изменить существующий запрос, чтобы ввести tid на основе image_id, найденного в основной части запроса? Я предполагаю, что мне нужен какой-то подзапрос, но это расширяет границы моих возможностей sql…

——————————————————————————————

ОБНОВЛЯЙТЕ для каждого запроса, вот структуры таблиц всех таблиц, используемых в запросе:

 -- Table structure for table `content_field_att_file`
--

CREATE TABLE IF NOT EXISTS `content_field_att_file` (
  `vid` int(10) unsigned NOT NULL DEFAULT '0',
  `nid` int(10) unsigned NOT NULL DEFAULT '0',
  `delta` int(10) unsigned NOT NULL DEFAULT '0',
  `field_att_file_fid` int(11) DEFAULT NULL,
  `field_att_file_list` tinyint(4) DEFAULT NULL,
  `field_att_file_data` text,
  PRIMARY KEY (`vid`,`delta`),
  KEY `nid` (`nid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

--
-- Table structure for table `content_field_related_images`
--

CREATE TABLE IF NOT EXISTS `content_field_related_images` (
  `vid` int(10) unsigned NOT NULL DEFAULT '0',
  `nid` int(10) unsigned NOT NULL DEFAULT '0',
  `delta` int(10) unsigned NOT NULL DEFAULT '0',
  `field_related_images_nid` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`vid`,`delta`),
  KEY `nid` (`nid`),
  KEY `field_related_images_nid` (`field_related_images_nid`),
  KEY `delta` (`delta`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

--
-- Table structure for table `files`
--

CREATE TABLE IF NOT EXISTS `files` (
  `fid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(10) unsigned NOT NULL DEFAULT '0',
  `filename` varchar(255) NOT NULL DEFAULT '',
  `filepath` varchar(255) NOT NULL DEFAULT '',
  `filemime` varchar(255) NOT NULL DEFAULT '',
  `filesize` int(10) unsigned NOT NULL DEFAULT '0',
  `status` int(11) NOT NULL DEFAULT '0',
  `timestamp` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`fid`),
  KEY `uid` (`uid`),
  KEY `status` (`status`),
  KEY `timestamp` (`timestamp`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=100810 ;

-- --------------------------------------------------------

--
-- Table structure for table `node`
--

CREATE TABLE IF NOT EXISTS `node` (
  `nid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `vid` int(10) unsigned NOT NULL DEFAULT '0',
  `type` varchar(32) NOT NULL DEFAULT '',
  `language` varchar(12) NOT NULL DEFAULT '',
  `title` varchar(255) NOT NULL DEFAULT '',
  `uid` int(11) NOT NULL DEFAULT '0',
  `status` int(11) NOT NULL DEFAULT '1',
  `created` int(11) NOT NULL DEFAULT '0',
  `changed` int(11) NOT NULL DEFAULT '0',
  `comment` int(11) NOT NULL DEFAULT '0',
  `promote` int(11) NOT NULL DEFAULT '0',
  `moderate` int(11) NOT NULL DEFAULT '0',
  `sticky` int(11) NOT NULL DEFAULT '0',
  `tnid` int(10) unsigned NOT NULL DEFAULT '0',
  `translate` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`nid`),
  UNIQUE KEY `vid` (`vid`),
  KEY `node_changed` (`changed`),
  KEY `node_created` (`created`),
  KEY `node_moderate` (`moderate`),
  KEY `node_promote_status` (`promote`,`status`),
  KEY `node_status_type` (`status`,`type`,`nid`),
  KEY `node_title_type` (`title`,`type`(4)),
  KEY `node_type` (`type`(4)),
  KEY `uid` (`uid`),
  KEY `tnid` (`tnid`),
  KEY `translate` (`translate`),
  KEY `status` (`status`,`type`,`created`),
  KEY `status_2` (`status`,`type`,`created`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=102682 ;

-- --------------------------------------------------------

--
-- Table structure for table `node_revisions`
--

CREATE TABLE IF NOT EXISTS `node_revisions` (
  `nid` int(10) unsigned NOT NULL DEFAULT '0',
  `vid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL DEFAULT '0',
  `title` varchar(255) NOT NULL DEFAULT '',
  `body` longtext NOT NULL,
  `teaser` longtext NOT NULL,
  `log` longtext NOT NULL,
  `timestamp` int(11) NOT NULL DEFAULT '0',
  `format` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`vid`),
  KEY `nid` (`nid`),
  KEY `uid` (`uid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=102690 ;

-- --------------------------------------------------------

--
-- Table structure for table `term_node`
--

CREATE TABLE IF NOT EXISTS `term_node` (
  `nid` int(10) unsigned NOT NULL DEFAULT '0',
  `vid` int(10) unsigned NOT NULL DEFAULT '0',
  `tid` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`tid`,`vid`),
  KEY `vid` (`vid`),
  KEY `nid` (`nid`),
  KEY `tid` (`tid`,`nid`),
  KEY `tid_2` (`tid`,`nid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  

Комментарии:

1. Я не понимаю проблемы. Вы уже подключаетесь к term_node. Почему вы не можете просто добавить tid в предложение select? Или вы имеете в виду, что вам нужно посмотреть другую запись term_node, чем та, к которой вы уже присоединились? Если да, то каковы критерии выбора для этой записи? В вашем примере вы просто говорите nid = . Это тот же nid, который уже есть в select? Если нет, то что это?

2. Потому что соединение при этом возвращает tid для n.nid . Мне нужен идентификатор tid для cfri.field_related_images_nid, который является частью начальной инструкции select.

Ответ №1:

Вы можете добавить второе объединение для term_node таблицы и добавить столбец в список выбора :

 SELECT DISTINCT n.title, nr.teaser, n.nid, DATE_FORMAT(FROM_UNIXTIME(n.created), '%M %e, %Y') AS date, f.filepath AS image, cfri.field_related_images_nid as image_id, tn_img.tid as image_tid

FROM node n JOIN node_revisions nr ON n.nid = nr.nid 
LEFT JOIN content_field_related_images cfri ON (n.nid = cfri.nid AND cfri.delta = 0) 
LEFT JOIN content_field_att_file cfaf ON cfri.field_related_images_nid = cfaf.nid 
LEFT JOIN files f ON cfaf.field_att_file_fid = f.fid  
JOIN term_node tn2 ON n.nid = tn2.nid
LEFT JOIN term_node tn_img ON cfri.field_related_images_nid = tn_img.nid

WHERE n.status = 1 
AND n.type = 'article'   
AND nr.body LIKE '%kimberly-clark%' 
AND tn2.tid = 143 
ORDER BY n.created DESC LIMIT 3
  

Это важная строка : LEFT JOIN term_node tn_img on cfri.field_related_images_nid = tn_img.nid не забудьте также добавить столбец в список выбора !

Возможно, мой запрос неверен, у нас не так много информации о структуре таблицы, если это не сработало, опубликуйте схему базы данных 🙂

обновлено, чтобы отразить обсуждение в комментариях

Комментарии:

1. Сначала я попробую ваш запрос; это установка drupal, поэтому база данных огромна. Если это не сработает, я попытаюсь вывести схему для соответствующих таблиц.

2. Нет, это вернуло более 3000 записей, когда их должно было быть только 3. Я постараюсь опубликовать информацию о таблице.

3. @EmmyS попробуйте заменить JOIN на INNER JOIN в добавленной строке.

4. О, так близко… но нам нужно возвращать записи узла, у которых нет связанного изображения (или у которых есть изображение, но у изображения нет tax. term.) Внутреннее объединение полностью устранило все записи, у которых нет изображения.

5. @EmmyS используйте LEFT JOIN тогда 🙂

Ответ №2:

Возможно, я чего-то не понимаю, но это должно сработать

 SELECT DISTINCT n.title, nr.teaser, n.nid, **tn2.tid** DATE_FORMAT(FROM_UNIXTIME(n.created), '%M %e, %Y') AS date, f.filepath AS image, cfri.field_related_images_nid as image_id 

FROM node n JOIN node_revisions nr ON n.nid = nr.nid 
JOIN term_node tn tn2 ON n.nid = tn2.nid
LEFT JOIN content_field_related_images cfri ON (n.nid = cfri.nid AND cfri.delta = 0) 
LEFT JOIN content_field_att_file cfaf ON cfri.field_related_images_nid = cfaf.nid 
LEFT JOIN files f ON cfaf.field_att_file_fid = f.fid  

WHERE n.status = 1 
AND n.type = 'article'   
AND nr.body LIKE '%kimberly-clark%' 
AND tn2.tid = 143 
ORDER BY n.created DESC LIMIT 3
  

Комментарии:

1. Смотрите комментарии к первоначальному сообщению; tn2.tid включен в предложение where, чтобы ограничить результаты n. записями, у которых tid равен 143. Я хочу включить результаты из cfri без ограничения на tid, при условии, что nid соответствует возвращенному cfri.related_images_nid в наборе записей.