您如何使连接子句显示来自相同 table 的 (ingredient1,ingredient2)

How can you make a join clause displaying (ingredient1,ingredient2) from the same table

我有 4 个 table,其中 2 个是这个问题所必需的:

CREATE TABLE Ingredient_sets
(
    recipe_id NUMBER(3,0),
    ingred_id NUMBER(3,0), 
    quantity NUMBER(5,2), 
    um VARCHAR2(10) NOT NULL), 
    comments VARCHAR2(100)
);

CREATE TABLE Ingredient 
(
    ingred_id NUMBER(3,0), 
    ingredient VARCHAR2(30)
);

我必须做一个加入声明。它应该显示成分 1、成分 2,其中成分在同一配方中(因此 recipe_id 相同),具有相同的计量单位(um)和相同的数量。

结果对应该只出现一次!

ingred_idIngredient 中的主键 table 和 Ingredient_sets 中的外键 table:

ALTER TABLE Ingredient
    MODIFY (CONSTRAINT ingred_id_pk PRIMARY KEY (ingred_id));

ALTER TABLE Ingredient_sets
    MODIFY (CONSTRAINT ingred_id_fk FOREIGN KEY (ingred_id) 
            REFERENCES Ingredient(ingred_id) ON DELETE CASCADE);

Recipe_id 是其 table 的主键。

直到现在我尝试了不同的连接语句,但没有任何效果

如果 table Ingredient_sets 有主键,解决方案会更简单。没有它,您可以使用 DISTINCT 删除重复项的查询。查询可能如下所示:

select distinct a.recipe_id, a.ingred_id, a.um, a.quantity
from Ingredient_sets a
join Ingredient_sets b 
  on a.recipe_id = b.recipe_id
 and a.ingred_id = b.ingred_id
 and a.um = b.um
 and a.quantity = b.quantity

在 recipe_id & um & 数量上使用自连接。
还有更高(或更低)的 ingred_id.
然后你只得到一次二重奏。

示例数据

CREATE TABLE Ingredient 
(
    ingred_id NUMBER(3,0),
    ingredient VARCHAR2(30), 
    CONSTRAINT ingred_id_pk PRIMARY KEY (ingred_id)
);

CREATE TABLE Ingredient_sets
(
    recipe_id NUMBER(3,0),
    ingred_id NUMBER(3,0), 
    quantity NUMBER(5,2), 
    um VARCHAR2(10) NOT NULL, 
    comments VARCHAR2(100), 
    CONSTRAINT ingred_id_fk FOREIGN KEY (ingred_id) 
            REFERENCES Ingredient(ingred_id) ON DELETE CASCADE
);

INSERT ALL
INTO Ingredient VALUES (1, 'Butter')
INTO Ingredient VALUES (2, 'Milk')
INTO Ingredient VALUES (3, 'Egg')
SELECT 1 FROM DUAL;

INSERT INTO Ingredient_sets 
(recipe_id, ingred_id, quantity, um, comments) 
SELECT 1, 1, 20.2, 'gram', 'greasy stuff' FROM DUAL UNION ALL
SELECT 1, 2, 20.2, 'gram', 'liquid stuff' FROM DUAL UNION ALL
SELECT 1, 3, 2.0, 'piece', 'slimey stuff' FROM DUAL 

查询:

select 
  set1.recipe_id
, set1.um
, set1.quantity
, set1.ingred_id as ingred_id1
, ing1.ingredient as ingredient1
, set2.ingred_id as ingred_id2
, ing2.ingredient as ingredient2
from Ingredient_sets set1
join Ingredient_sets set2
  on set2.recipe_id = set1.recipe_id
 and set2.um = set1.um
 and set2.quantity = set1.quantity
 and set2.ingred_id > set1.ingred_id
left join Ingredient ing1 on ing1.ingred_id = set1.ingred_id
left join Ingredient ing2 on ing2.ingred_id = set2.ingred_id
RECIPE_ID | UM   | QUANTITY | INGRED_ID1 | INGREDIENT1 | INGRED_ID2 | INGREDIENT2
--------: | :--- | -------: | ---------: | :---------- | ---------: | :----------
        1 | gram |     20.2 |          1 | Butter      |          2 | Milk       

或者使用 COUNT OVER 过滤那些没有唯一的 um 和每组数量的。

select *
from
(
  select 
    ingset.*
  , ing.ingredient
  , count(*) over (partition by recipe_id, um, quantity) as same
  from Ingredient_sets ingset
  left join Ingredient ing on ing.ingred_id = ingset.ingred_id
) q
where same > 1
order by recipe_id, um, quantity
RECIPE_ID | INGRED_ID | QUANTITY | UM   | COMMENTS     | INGREDIENT | SAME
--------: | --------: | -------: | :--- | :----------- | :--------- | ---:
        1 |         1 |     20.2 | gram | greasy stuff | Butter     |    2
        1 |         2 |     20.2 | gram | liquid stuff | Milk       |    2

db<>fiddle here