【发布时间】:2014-02-23 01:06:59
【问题描述】:
我需要从多个表中SELECT 来获取如下结果表:
+--------+-------+-------------------+----------------------+
| itemID | level | studyPhraseString | meaningPhraseStrings |
+--------+-------+-------------------+----------------------+
| 1 | 4 | la maison | house |
+--------+-------+-------------------+----------------------+
| 2 | 3 | voler | to fly,to steal |
+--------+-------+-------------------+----------------------+
注意:studyPhraseString 和 meaningPhraseStrings 应该是由 word 表中的值组成的串联字符串。
我的桌子:
项目
CREATE TABLE `item` (
`itemID` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
`groupID` bigint(11) unsigned NOT NULL,
`studyLang` varchar(5) NOT NULL,
`meaningLang` varchar(5) NOT NULL,
`studyPhraseID` bigint(11) unsigned NOT NULL,
PRIMARY KEY (`itemID`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1;
意义
CREATE TABLE `meaning` (
`meaningID` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
`itemID` bigint(11) unsigned NOT NULL,
`meaningPhraseID` bigint(11) unsigned NOT NULL,
`meaningIndex` int(11) unsigned NOT NULL,
PRIMARY KEY (`meaningID`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=latin1;
短语
CREATE TABLE `phrase` (
`phraseID` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
`phraseLang` varchar(5) NOT NULL DEFAULT '',
PRIMARY KEY (`phraseID`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=latin1;
phrase_word
CREATE TABLE `phrase_word` (
`phrase_wordID` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
`phraseID` bigint(11) unsigned NOT NULL,
`wordID` bigint(11) unsigned NOT NULL,
`wordIndex` int(11) unsigned NOT NULL,
PRIMARY KEY (`phrase_wordID`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=latin1;
状态
CREATE TABLE `status` (
`statusID` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
`itemID` bigint(11) unsigned NOT NULL,
`level` tinyint(1) unsigned NOT NULL DEFAULT '0',
`nextReviewTime` int(11) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`statusID`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1;
单词
CREATE TABLE `word` (
`wordID` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
`string` varchar(64) NOT NULL DEFAULT '',
PRIMARY KEY (`wordID`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
我已经编写了以下 SELECT 语句:
SELECT item.itemID, status.level,
(SELECT GROUP_CONCAT(word.string ORDER BY phrase_word.wordIndex SEPARATOR ' ')
FROM word INNER JOIN phrase_word ON word.wordID=phrase_word.wordID
INNER JOIN item AS subItem ON phrase_word.phraseID=subItem.studyPhraseID
WHERE subItem.itemID=item.itemID
GROUP BY subItem.itemID
) AS studyPhraseString
FROM item INNER JOIN status ON item.itemID=status.itemID
WHERE item.groupID=5
ORDER BY status.statusID DESC
这有效,但不包括meaningPhraseString。我不知道如何将单词连接成短语并将短语连接成一个字符串,用 , 分隔
我尝试了嵌套的 GROUP_CONCAT 子句,但没有成功(子查询返回超过 1 行):
问题:
应如何编写此语句以包含meaningPhraseStrings?提前致谢。
PS:我希望这是一个单一的查询
我尝试了以下方法,但失败了。为什么?它有两个级别的相关查询。
SELECT
item.itemID,
status.level,
(
SELECT GROUP_CONCAT(word.string ORDER BY phrase_word.wordIndex SEPARATOR ' ')
FROM word INNER JOIN phrase_word ON word.wordID=phrase_word.wordID
INNER JOIN item AS subItem ON phrase_word.phraseID=subItem.studyPhraseID
WHERE subItem.itemID=item.itemID
GROUP BY subItem.itemID
) AS studyPhraseString,
(
SELECT GROUP_CONCAT(meaningPhraseString SEPARATOR '.')
FROM (
(
SELECT GROUP_CONCAT(word.string ORDER BY phrase_word.wordIndex SEPARATOR ' ') AS meaningPhraseString
FROM word INNER JOIN phrase_word ON word.wordID=phrase_word.wordID
INNER JOIN meaning ON phrase_word.phraseID=meaning.meaningPhraseID
INNER JOIN item AS subItem ON meaning.itemID=subItem.itemID
WHERE subItem.itemID=item.itemID #This fails
GROUP BY meaning.meaningPhraseID
) AS meaningPhraseString
)
) AS meaningPhraseStrings
FROM item INNER JOIN status ON item.itemID=status.itemID
WHERE item.groupID=5
ORDER BY item.itemID DESC
样本数据:
INSERT INTO `status` VALUES (22,22,0,0),(23,23,0,0),(24,25,0,0),(25,24,0,0),(26,26,0,0);
INSERT INTO `item` VALUES (22,5,'fr','en',49),(23,5,'fr','en',48),(24,5,'fr','en',56),(25,5,'fr','en',50),(26,5,'fr','en',57);
INSERT INTO `meaning` VALUES (27,22,51,0),(28,23,52,0),(29,23,54,1),(30,24,59,0),(31,24,61,1),(32,25,53,0),(33,25,55,1),(34,26,58,0),(35,26,60,1);
INSERT INTO `phrase` VALUES (48,'fr'),(49,'fr'),(50,'fr'),(51,'en'),(52,'en'),(53,'en'),(54,'en'),(55,'en'),(56,'fr'),(57,'fr'),(58,'en'),(59,'en'),(60,'en'),(61,'en');
INSERT INTO `word` VALUES (46,'l\'autobus'),(47,'bus'),(48,'pourquoi'),(49,'comment'),(50,'why'),(51,'ça'),(52,'va?'),(53,'voler'),(54,'incroyable'),(55,'how'),(56,'is'),(57,'to'),(58,'are'),(59,'incredible'),(60,'that?'),(61,'you?'),(62,'fly'),(63,'amazing'),(64,'hi'),(65,'steal');
INSERT INTO `phrase_word` VALUES (86,49,46,0),(87,51,47,0),(88,48,48,0),(89,50,49,0),(90,52,50,0),(91,54,50,0),(92,50,51,1),(93,50,52,2),(94,57,53,0),(95,53,55,0),(96,56,54,0),(97,54,56,1),(98,53,58,1),(99,58,57,0),(100,59,59,0),(101,54,60,2),(102,53,61,2),(103,58,62,1),(104,61,63,0),(105,60,57,0),(106,55,64,0),(107,60,65,1);
最终答案:
SELECT i.itemID,
s.level,
sp.studyPhraseString,
GROUP_CONCAT(mp.meaningPhraseString
SEPARATOR ', ') AS meaningPhraseStrings
FROM item AS i
JOIN meaning AS m ON i.itemID = m.itemID
JOIN status AS s ON i.itemID = s.itemID
JOIN (
SELECT subItem.studyPhraseID,
GROUP_CONCAT(word.string
ORDER BY phrase_word.wordIndex
SEPARATOR ' ') AS studyPhraseString
FROM word
JOIN phrase_word
ON word.wordID=phrase_word.wordID
JOIN item AS subItem
ON phrase_word.phraseID=subItem.studyPhraseID
GROUP BY subItem.studyPhraseID
) AS sp ON i.studyPhraseID = sp.studyPhraseID
JOIN (
SELECT meaning.meaningPhraseID,
GROUP_CONCAT(word.string
ORDER BY phrase_word.wordIndex
SEPARATOR ' ') AS meaningPhraseString
FROM word
JOIN phrase_word ON word.wordID=phrase_word.wordID
JOIN meaning ON phrase_word.phraseID=meaning.meaningPhraseID
JOIN item AS subItem ON meaning.itemID=subItem.itemID
GROUP BY meaning.meaningPhraseID
) AS mp ON m.meaningPhraseID = mp.meaningPhraseID
GROUP BY i.itemID, s.level, sp.studyPhraseString
ORDER BY i.itemID, s.level, sp.studyPhraseString
【问题讨论】:
-
GROUP_CONCAT()在查询中几乎没有意义,除非伴随着GROUP BY子句。 -
我已将 GROUP BY 添加到子查询中,但没有任何区别。我同意应该有一个 GROUP BY。
-
我正在尝试回答您的问题,但我不太了解您的架构。能否提供一些示例表数据?
标签: mysql sql select subquery group-concat