Здесь мы идем снова ...
[EDIT] Внизу есть обновление с SQL для создания тестовой базы данных.[EDIT]
Я несколько дней боролся с довольно сложным для меня SQL-запросом.Я бы никогда не продвинулся так далеко без всей огромной помощи со стороны SO, которая научила меня большому количеству SQL.
Я постараюсь показать вам настройки, чтобы вы поняли, что я пытаюсь сделать.Пожалуйста, будьте терпеливы ...
Фон
У меня есть одна таблица с целочисленными атрибутами (IntegerAttributes).Идентификатор представляет собой идентификатор элемента, где ключ представляет собой имя атрибута, прикрепленного к элементу с идентификатором «ID», а значение представляет собой значение атрибута и может быть только целым числом.Один элемент может иметь от 0 до многих атрибутов.
IntegerAttributes
ID Key Value
1 Location 3
1 Color 5
2 Location 1
3 Color 3
Значением атрибута «Местоположение» является идентификатор в другой таблице под названием «Местоположения»
Locations
ID Location etc...
1 Boston
2 Manilla
3 Stockholm
4 Beijing
Значение атрибута«Цвет» - это идентификатор в другой таблице с именем «Цвета»
Locations
ID Color
1 Blue
2 Black
3 White
4 Red
5 Green
. Существует также аналогичная таблица для строк (StringAttributes), которая работает так же, как IntegerAttributes, за исключением того, что столбец «Значение» - это текст.И IntegerAttributes, и StringAttributes объединяются и преобразуются в строки с помощью UNION ALL.
На этом этапе таблица, содержащая каждый элемент, очень проста:
ID Checkin
1 2010-01-22 11:28:18
2 2010-01-21 16:27:54
3 2010-01-20 18:40:07
Пока все понятно, но теперьэто усложняется:
Это SQL-запрос, который я использую для извлечения всех атрибутов и объединения их в строку JSON и извлечения данных элемента
SELECT
i.ID,
i.Checkin,
CONCAT('{\"Date\":\"',i.Checkin,'\",', GROUP_CONCAT('\"',Attribute.key, '\":\"', CONVERT(Attribute.value,CHAR), '\"'), '}') as Attributes
# , l.Location
FROM (
SELECT ItemID, ats.Key, ats.Value
FROM attributeStrings as ats
UNION ALL
SELECT ItemID, ati.Key, ati.Value
FROM attributeIntegers as ati
) Attribute
JOIN Items i ON i.ID = Attribute.ItemID
# JOIN locations l ON (Attribute.Key = 'Location' AND l.ID = Attribute.Value)
GROUP BY ItemID
ORDER BY i.ID DESC
Как видите, я отметил двая вернусь к ним в ближайшее время.
Проблема
Результат запроса выше будет примерно таким:
ID Checkin Attributes
1 2010-01-22 11:28:18 {"Date":"2010-01-22 11:28:18","Location":"3","Color":"5"}
2 2010-01-21 16:27:54 {"Date":"2010-01-21 16:27:54","Location":"1"}
3 2010-01-20 18:40:07 {"Date":"2010-01-20 18:40:07","Color":"3"}
Пока все хорошо.
Но теперь я хотел бы включить поиск в «Location» (и, в конце концов, в «Color» или другие атрибуты с идентификатором lookup-ID).
Если я раскомментирую две строки взапрос выше
# , l.Location
# JOIN locations l ON (Attribute.Key = 'Location' AND l.ID = Attribute.Value)
Я получаю результаты только в том случае, если единственным атрибутом является «Местоположение», а поле «Атрибуты» теперь будет содержать только атрибуты «Дата» и «Местоположение».
ID Checkin Attributes Location
2 2010-01-21 16:27:54 {"Date":"2010-01-21 16:27:54","Location":"1"} Boston
Желаемое резюмеlt
Результат, который я хочу получить, такой же, как и раньше, но с дополнительным столбцом с атрибутом «Местоположение» (а затем и с другими столбцами поиска), который был найден в Locations.хочу:
ID Checkin Attributes Location Color
1 2010-01-22 11:28:18 {"Date":"2010-01-22 11:28:18","Location":"3","Color":"5"} Stockholm Green
2 2010-01-21 16:27:54 {"Date":"2010-01-21 16:27:54","Location":"1"} Boston null
3 2010-01-20 18:40:07 {"Date":"2010-01-20 18:40:07","Color":"3"} null White
Спасибо, что прочитали все здесь: D Я пытался уточнить с IF EXISTS, но я не могу понять, как это сделать.
[РЕДАКТИРОВАТЬ] SQL ДЛЯ СОЗДАНИЯ ИСПЫТАТЕЛЬНОЙ БАЗЫ ДАННЫХ [РЕДАКТИРОВАТЬ]
-- MySQL Administrator dump 1.4
--
-- ------------------------------------------------------
-- Server version 5.1.47-community
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
--
-- Create schema swebussandbox
--
CREATE DATABASE IF NOT EXISTS SODatabase;
USE SODatabase;
--
-- Definition of table `attributeintegers`
--
DROP TABLE IF EXISTS `attributeintegers`;
CREATE TABLE `attributeintegers` (
`ItemID` int(10) unsigned NOT NULL,
`Key` varchar(45) NOT NULL,
`Value` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`ItemID`,`Key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
--
-- Dumping data for table `attributeintegers`
--
/*!40000 ALTER TABLE `attributeintegers` DISABLE KEYS */;
INSERT INTO `attributeintegers` (`ItemID`,`Key`,`Value`) VALUES
(4,'Color',17),
(4,'Location',3),
(5,'Location',2),
(6,'Location',6),
(7,'Color',15),
(8,'Location',8),
(9,'Location',10),
(10,'Color',15),
(10,'Location',2),
(11,'Color',15),
(11,'Location',4),
(12,'Color',15),
(12,'Location',3),
(13,'Color',15),
(13,'Location',8),
(14,'Location',3),
(15,'Location',6),
(16,'Color',18),
(18,'Color',15),
(18,'Location',4);
/*!40000 ALTER TABLE `attributeintegers` ENABLE KEYS */;
--
-- Definition of table `attributestrings`
--
DROP TABLE IF EXISTS `attributestrings`;
CREATE TABLE `attributestrings` (
`ItemID` int(10) unsigned NOT NULL DEFAULT '0',
`Key` varchar(45) NOT NULL DEFAULT '_NA_',
`Value` text,
PRIMARY KEY (`ItemID`,`Key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
--
-- Dumping data for table `attributestrings`
--
/*!40000 ALTER TABLE `attributestrings` DISABLE KEYS */;
INSERT INTO `attributestrings` (`ItemID`,`Key`,`Value`) VALUES
(5,'Type','BagForm'),
(6,'Type','BagForm'),
(9,'Type','BagForm'),
(10,'Type','BagForm'),
(11,'Type','BagForm'),
(12,'Brand','Bogcase'),
(12,'Type','BagForm'),
(14,'Type','BagForm'),
(15,'Brand','Carryline World Wide'),
(15,'Type','BagForm'),
(16,'Brand','Fjällräven'),
(16,'Type','BagForm'),
(17,'Brand','Packard Bell'),
(17,'Tech','ComputerForm'),
(17,'Type','TechGUI');
/*!40000 ALTER TABLE `attributestrings` ENABLE KEYS */;
--
-- Definition of table `colors`
--
DROP TABLE IF EXISTS `colors`;
CREATE TABLE `colors` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Color` varchar(45) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
--
-- Dumping data for table `colors`
--
/*!40000 ALTER TABLE `colors` DISABLE KEYS */;
INSERT INTO `colors` (`ID`,`Color`) VALUES
(1,'Multicolored'),
(2,'Black'),
(3,'White'),
(4,'Red'),
(5,'Green'),
(6,'Blue'),
(7,'Yellow'),
(8,'Black'),
(9,'Gold'),
(10,'Bown'),
(11,'Purpul'),
(12,'Pink'),
(13,'Orange'),
(14,'Gray'),
(15,'Transparent');
/*!40000 ALTER TABLE `colors` ENABLE KEYS */;
--
-- Definition of table `items`
--
DROP TABLE IF EXISTS `items`;
CREATE TABLE `items` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`CheckIn` datetime DEFAULT NULL,
`Line` int(10) unsigned DEFAULT NULL,
`TypeID` int(10) unsigned DEFAULT NULL,
`SizeID` int(10) unsigned DEFAULT NULL,
`ColorID` int(10) unsigned DEFAULT NULL,
`MaterialID` int(10) unsigned DEFAULT NULL,
`CheckOut` datetime DEFAULT NULL,
`LocationID` int(10) unsigned DEFAULT NULL,
`Notes` text,
`Tur` int(10) unsigned DEFAULT NULL,
`Bus` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`ID`),
FULLTEXT KEY `NoteIndex` (`Notes`)
) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 PACK_KEYS=1;
--
-- Dumping data for table `items`
--
/*!40000 ALTER TABLE `items` DISABLE KEYS */;
INSERT INTO `items` (`ID`,`CheckIn`) VALUES
(4,'2010-12-03 02:04:38'),
(5,'2010-12-27 02:11:25'),
(6,'2010-12-27 02:14:28'),
(7,'2010-12-25 02:17:09'),
(8,'2010-12-24 02:33:49'),
(9,'2011-01-06 07:48:16'),
(10,'2011-01-06 07:47:09'),
(11,'2010-12-31 10:53:26');
/*!40000 ALTER TABLE `items` ENABLE KEYS */;
--
-- Definition of table `locations`
--
DROP TABLE IF EXISTS `locations`;
CREATE TABLE `locations` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Location` varchar(45) NOT NULL,
`Group` int(10) unsigned NOT NULL DEFAULT '1',
`Address` text,
`Phone` varchar(20) DEFAULT NULL,
`Contact` varchar(45) DEFAULT NULL,
`Hours` varchar(45) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
--
-- Dumping data for table `locations`
--
/*!40000 ALTER TABLE `locations` DISABLE KEYS */;
INSERT INTO `locations` (`ID`,`Location`) VALUES
(1,'Boston'),
(2,'Stockholm'),
(3,'Manilla'),
(4,'Berlin'),
(5,'Oslo'),
(6,'Paris'),
(7,'London'),
(8,'Amsterdam'),
(9,'Helsinki'),
(10,'Kopenhagen'),
(11,'Barselona'),
(12,'Luxenbourg'),
(13,'Milano');
/*!40000 ALTER TABLE `locations` ENABLE KEYS */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
Я опробовал предложение от Тумблер с этим обновленным запросом:
SELECT
i.ID,
i.Checkin,
CONCAT('{\"Date\":\"',i.Checkin,'\",', GROUP_CONCAT('\"',Attribute.key, '\":\"', CONVERT(Attribute.value,CHAR), '\"'), '}') as Attributes,
COALESCE(l.Location,null) as Location,
COALESCE(c.Color,null) as Color
FROM (
SELECT ItemID, ats.Key, ats.Value
FROM attributeStrings as ats
UNION ALL
SELECT ItemID, ati.Key, ati.Value
FROM attributeIntegers as ati
) Attribute
LEFT JOIN locations l ON (Attribute.Key = 'Location' AND l.ID = Attribute.Value)
LEFT JOIN Colors c ON (Attribute.Key = 'Color' AND c.ID = Attribute.Value)
JOIN Items i ON i.ID = Attribute.ItemID
GROUP BY ItemID
ORDER BY i.ID DESC
... но он отображает все атрибуты, но только для элементов, которые имеют местоположение или цвет в качестве атрибута ONLY.