У меня проблемы с SELECT
. Я работаю в MySQL.
Я хочу получить электронное письмо "consumidor", которое купило продукты ("Produto"), которые включают в себя все "Элементо".
Я сделал это:
SELECT C.email
FROM Consumidor C, composto composto, compra compra
WHERE C.numero = compra.consumidor
HAVING COUNT(DISTINCT composto.elemento) = ( SELECT COUNT(*)
FROM Elemento E)
Но это не сработало. У меня есть только один результат, и я знаю, что там больше. Я знаю, что между WHERE
и HAVING
отсутствует недостающий материал.
ТАБЛИЦЫ
Create table Consumidor (
numero int(9),
email varchar(30) not null,
sexo char(1) not null,
nascimento date not null,
constraint Consumidor_sexo_RI001 check (sexo in ('F','M')),
constraint Consumidor_unique_RI002 unique(email),
constraint pk_Consumidor primary key (numero)
);
Create table Elemento (
codigo char(3),
nome varchar(25) not null,
pegadaEcologica int(2) not null,
saude int(2) not null,
constraint pk_Elemento primary key (codigo)
);
Create table Produto (
codigo int(6),
marca int(7),
nome varchar(50) not null,
tipo char(10),
comercioJusto char(1),
constraint Produto_tipo_RI004 check (tipo in ('alimentac','lar','jardim','automov','viagem','electrodom')),
constraint Produto_comercioJusto_RI005 check (comercioJusto in ('A','B','C','D')),
constraint fk_Produto_marca foreign key (marca) references Marca(numero) on delete cascade,
constraint pk_Produto primary key (codigo,marca)
);
Create table compra (
produto int(6),
prodMarca int(7),
consumidor int(9),
quantidade decimal(10,3) not null,
constraint compra_quantidade_RI006 check (quantidade>0),
constraint fk_compra_produto foreign key (produto,prodMarca) references Produto(codigo,marca) on delete cascade,
constraint fk_compra_consumidor foreign key (consumidor) references Consumidor(numero) on delete cascade,
constraint pk_compra primary key (produto,prodMarca,consumidor)
);
Create table composto (
produto int(6),
prodMarca int(7),
elemento char(3),
percentagem decimal(4,1) not null,
constraint composto_percentagem_RI007 check (percentagem>0 and percentagem<=100),
constraint fk_composto_produto foreign key (produto,prodMarca) references Produto(codigo,marca) on delete cascade,
constraint fk_composto_elemento foreign key (elemento) references Elemento(codigo) on delete cascade,
constraint pk_composto primary key (produto,prodMarca,elemento)
);
Неправильное использование функции HAVING
. Что вы говорите, так как количество elemento
(Product Details) должно совпадать с количеством вашей Composto
(Products to Product Details).
Причина, по которой вы получаете только 1 строку, заключается в том, что вы присоединяетесь к Count
или количеству строк из таблицы "Сведения о продукте" к количеству элементов, которые вы получили.
Попробуй это:
SELECT COUNT(*) FROM Elemento E
и вы увидите, что есть только одна единственная сумма, которая возвращается (количество фактической информации о товаре у вас есть).
Теперь попробуйте:
SELECT COUNT(DISTINCT composto.elemento) FROM composto
и вы увидите, что цифры совпадают.
Все, что вы делаете, это подсчет количества элементов. Это явно не то, что вы ищете, поскольку это не правильный способ улучшить ваши результаты.
Кроме того, вы не правильно присоединяетесь к своим таблицам. MySQL - это " реляционная база данных ", что означает, что вам нужно конкретно определить "отношения" между вашими объектами (таблицами).
Для начала вам необходимо обновить свой запрос, чтобы исправить свои соединения:
SELECT Customer.email, ProductDetails.nome
FROM Consumidor Customer
-- Joins the Consumidor (consumer) table to the Compra (sales) table
INNER JOIN compra Sales
ON Customer.numero = Sales.consumidor
-- Joins the sales to the Produto (products) table
INNER JOIN Producto Product
ON Sales.produto = Product.codigo
-- Joins the composto (Composite Key) table to the elemento (Product Details) table
INNER JOIN composto
ON composto.produto = Product.codigo
-- Now get the Product details
INNER JOIN elemento ProductDetails
ON composto.elemento = ProductDetails.codigo
Теперь ваши соединения должны работать правильно, вы получите Person (Customer), продукты, которые они купили (compra), и информацию о продуктах.
Я предполагаю, что вы хотите, это подмножество Produto
(Products). Если это правильно, то вам нужно правильно определить ваши предикаты, используя предложение "WHERE":
SELECT Customer.email, ProductDetails.nome
FROM Consumidor Customer
-- Joins the Consumidor (consumer) table to the Compra (sales) table
INNER JOIN compra Sales
ON Customer.numero = Sales.consumidor
-- Joins the sales to the Produto (products) table
INNER JOIN Producto Product
ON Sales.produto = Product.codigo
-- Joins the composto (Composite Key) table to the elemento (Product Details) table
INNER JOIN composto
ON composto.produto = Product.codigo
-- Now get the Product details
INNER JOIN elemento ProductDetails
ON composto.elemento = ProductDetails.codigo
-- You can search for whatever matches your criteria here
WHERE Customer.nome = 'Möoz' -- Finds all products that user 'Möoz' has bought
Вы также можете добавить или удалить предикаты в своем предложении WHERE, чтобы уточнить ваш поиск:
WHERE ProductDetails.pegadaEcologica = 'Low' --searches for a 'low ecological footprint' product only
или же
WHERE ProductDetails.nome = 'Black Show' -- Searches for black shoes in the name of the product
или же
WHERE ProductDetails.codigo = 35 -- Searches for the item with the ID of 35
....
Я не могу проверить это, поэтому вы можете получить некоторые синтаксические ошибки. Попробуйте и посмотрите, работает ли это:
-- Get e-mail of consumer who bought products which include all elements
SELECT cdr.email
FROM compra cmp -- Get all purchases
INNER JOIN consumidor cdr ON cmp.consumidor = cdr.numero -- Get consumer info
WHERE (cmp.produto, cmp.prodMarca) IN ( -- Only look at purchases which included products that included all elements
SELECT pto.codigo, pto.marca
FROM produto pto -- Get all products
INNER JOIN composto cpt ON pto.codigo = cpt.produto AND cpt.prodMarca = pto.marca -- Get all elements defined for each product
HAVING COUNT(*) = (SELECT COUNT(*) FROM elemento) -- Only return products that have all elements
GROUP BY pto.codigo, pto.marca
);
Кроме того, вы можете захотеть сохранить одинаковые или похожие имена столбцов для ссылок на PK/FK. Это упрощает чтение и понимание вашей SQL/схемы. Дайте мне знать, если это сработает.