问题描述
我从业务合作伙伴那里继承了一个项目,并试图将其添加到其中,但是在这里却遇到了麻烦。 这是一个由7个表格组成的鸡尾酒数据库。
drinks (ID,drinkName,lu_category,lu_glassware,lu_IBA)
category (categoryID,category)
glassware (glasswareID,glassware)
ingredients (ingredientID,ingredient,notes)
measure (measureID,measure)
IBA (IBAID,IBA)
ingredient_drinks_measure (idmID,drinkID,ingredientID,measureID)
SELECT dbo.drinks.id AS [drinkID],dbo.drinks.drinkName,dbo.category.category,dbo.glassware.glassware,dbo.IBA.IBA,string_agg(measure.measure + ' ' + ingredients.ingredient,',') as [Ingredients]
FROM dbo.glassware
RIGHT OUTER JOIN dbo.measure
LEFT OUTER JOIN dbo.ingredient_drinks_measure ON dbo.measure.measureID = dbo.ingredient_drinks_measure.measureID
RIGHT OUTER JOIN dbo.ingredients ON dbo.ingredient_drinks_measure.ingredientID = dbo.ingredients.ingredientID
RIGHT OUTER JOIN dbo.drinks ON dbo.ingredient_drinks_measure.drinkID = dbo.drinks.id
LEFT OUTER JOIN dbo.IBA ON dbo.drinks.lu_IBA = dbo.IBA.IBAID ON dbo.glassware.glasswareID = dbo.drinks.lu_glassware
LEFT OUTER JOIN dbo.category ON dbo.drinks.lu_category = dbo.category.categoryID
GROUP BY dbo.drinks.id,dbo.drinks.imagePath,dbo.drinks.dateModified,dbo.IBA.IBA
返回
drinkID | drinkName | category | glassware | IBA | ingredients
11000 | Mojito | Cocktail | Highball glass | Contemporary Classics | 2-3 oz Jamaican Rum,Juice of 1 Lime,2 tsp Superfine Sugar
我现在需要在每种饮料中添加标签
(目前)只有22个标签,每种饮料都可以关联1到22个标签(这些标签包括“万圣节”,“圣诞节”,“打孔碗”,“早餐”,“晚餐聚会”,“果味”,“笨拙”等)。
我有一个tags table (id,tag)
,我有一个drinkTags table (drinkID,tagID)
坐在中间,将饮料和标签结合在一起(两者的CREATE脚本都在下面)。
但是,无论如何尝试,当我添加查询的联接和TAGS的伴随的string_agg列(逗号分隔的聚合列)时,至少有一个string_agg列会重复和/或得到多个每杯饮料。 像这样:
drinkID | drinkName | category | glassware | IBA | ingredients
11000 | Mojito | Cocktail | Highball glass | Contemporary Classics | 2-3 oz Jamaican Rum,2 tsp Superfine Sugar,2-3 oz Jamaican Rum,2 tsp Superfine Sugar
或者这个:
drinkID | drinkName | category | glassware | IBA | tags | ingredients
11000 | Mojito | Cocktail | Highball glass | Contemporary Classics | Alcoholic | 2-3 oz Jamaican Rum,2 tsp Superfine Sugar
11000 | Mojito | Cocktail | Highball glass | Contemporary Classics | IBA | 2 tsp Superfine Sugar,2-3 oz Jamaican Rum
11000 | Mojito | Cocktail | Highball glass | Contemporary Classics | USA | 2-3 oz Jamaican Rum,2 tsp Superfine Sugar
有什么想法吗?即使能为我提供我在所有研究中都被忽略的东西,我也将不胜感激。
如果需要,这里是CREATE脚本。
/****** Object: Table [dbo].[drinks] Script Date: 9/15/2020 1:25:57 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[drinks](
[id] [int] IDENTITY(1,1) NOT NULL,[drinkName] [varchar](37) NOT NULL,[lu_category] [int] NULL,[lu_IBA] [int] NULL,[lu_glassware] [int] NULL
CONSTRAINT [PK__drinks_c__2B658F5CD9E4315A] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF,STATISTICS_norECOmpuTE = OFF,IGnorE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON,OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[category] Script Date: 9/15/2020 1:27:18 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[category](
[categoryID] [int] IDENTITY(1,[category] [nvarchar](50) NULL,CONSTRAINT [PK__category__23CAF1F80317C8FA] PRIMARY KEY CLUSTERED
(
[categoryID] ASC
)WITH (PAD_INDEX = OFF,OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[drinkTags] Script Date: 9/15/2020 1:27:54 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[drinkTags](
[drinkID] [int] NOT NULL,[tagID] [int] NOT NULL,CONSTRAINT [PK_drinkTags_1] PRIMARY KEY CLUSTERED
(
[drinkID] ASC,[tagID] ASC
)WITH (PAD_INDEX = OFF,OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[glassware] Script Date: 9/15/2020 1:28:08 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[glassware](
[glasswareID] [int] IDENTITY(1,[glassware] [nvarchar](50) NULL,PRIMARY KEY CLUSTERED
(
[glasswareID] ASC
)WITH (PAD_INDEX = OFF,OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[IBA] Script Date: 9/15/2020 1:28:19 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[IBA](
[IBAID] [int] IDENTITY(1,[IBA] [nvarchar](50) NULL,PRIMARY KEY CLUSTERED
(
[IBAID] ASC
)WITH (PAD_INDEX = OFF,OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[ingredient_drinks_measure] Script Date: 9/15/2020 1:28:32 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[ingredient_drinks_measure](
[idmID] [int] IDENTITY(1,[drinkID] [int] NULL,[ingredientID] [int] NULL,[measureID] [int] NULL,PRIMARY KEY CLUSTERED
(
[idmID] ASC
)WITH (PAD_INDEX = OFF,OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[ingredients] Script Date: 9/15/2020 1:28:44 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[ingredients](
[ingredientID] [int] IDENTITY(1,[ingredient] [nvarchar](150) NULL
PRIMARY KEY CLUSTERED
(
[ingredientID] ASC
)WITH (PAD_INDEX = OFF,OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXtimage_ON [PRIMARY]
GO
/****** Object: Table [dbo].[measure] Script Date: 9/15/2020 1:29:14 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[measure](
[measureID] [int] IDENTITY(1,[measure] [nvarchar](50) NULL,PRIMARY KEY CLUSTERED
(
[measureID] ASC
)WITH (PAD_INDEX = OFF,OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[tags] Script Date: 9/15/2020 1:29:25 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tags](
[id] [int] IDENTITY(1,[tag] [nvarchar](50) NOT NULL,CONSTRAINT [PK_drinkTags] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF,OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
解决方法
解决方案1:
饮料与标签是否存在一对一关系?如果是这样,那么您要做的就是在饮料表中添加一个标签列。这将是解决问题的非规范化方法。
解决方案2:
如果饮料与标签实体没有一对一的关系。
哪个表存储饮料和标签之间的关系?如果没有此表,则需要创建一个表并填充数据。如果您在创建饮料标签关系方面需要帮助,那么我可以为您提供帮助。然后,您将需要更新SQL以使用标签喝酒关系来获取单个记录,并在SQL中添加标签字段。
希望以下查询可以解决您的问题。我添加了一个string_agg字段以返回与饮料相关的所有标签和两个INNER JOINS。
SELECT dbo.drinks.id AS [drinkID],dbo.drinks.drinkName,dbo.category.category,dbo.glassware.glassware,dbo.IBA.IBA,string_agg(measure.measure + ' ' + ingredients.ingredient,',') as [Ingredients],string_agg(dbo.tags.tag,‘) as [Tags]
FROM dbo.glassware
RIGHT OUTER JOIN dbo.measure
LEFT OUTER JOIN dbo.ingredient_drinks_measure ON dbo.measure.measureID = dbo.ingredient_drinks_measure.measureID
RIGHT OUTER JOIN dbo.ingredients ON dbo.ingredient_drinks_measure.ingredientID = dbo.ingredients.ingredientID
RIGHT OUTER JOIN dbo.drinks ON dbo.ingredient_drinks_measure.drinkID = dbo.drinks.id
LEFT OUTER JOIN dbo.IBA ON dbo.drinks.lu_IBA = dbo.IBA.IBAID ON dbo.glassware.glasswareID = dbo.drinks.lu_glassware
LEFT OUTER JOIN dbo.category ON dbo.drinks.lu_category = dbo.category.categoryID
INNER JOIN dbo.drinkTags.drinkID = dbo.drinks.id
INNER JOIN dbo.tags.id = dbo.drinkTags.tagID
GROUP BY dbo.drinks.id,dbo.drinks.imagePath,dbo.drinks.dateModified,dbo.IBA.IBA
,
经过大量研究,我找到了一个适用于我的解决方案。这确实假定每个DrinkID至少有一个标签,但是我现在可以处理。
;WITH a AS
(
SELECT
d.id,d.drinkName as [Name],c.category as [Category],g.glassware as [Glass],b.IBA as [IBA],string_agg(m.measure + ' ' + i.ingredient,d.instructions as [Instructions],string_agg(i.notes,') as [IngredientNotes],d.addedInfo as [Additional Information],d.imagePath as [Image]
FROM drinks d
JOIN category c on c.categoryID = d.lu_category
JOIN glassware g on g.glasswareID = d.lu_glassware
LEFT JOIN IBA b on b.IBAID = d.lu_IBA
JOIN ingredient_drinks_measure idm on idm.drinkID = d.id
JOIN ingredients i on i.ingredientID = idm.ingredientID
JOIN measure m on m.measureID = idm.measureID
group by d.id,d.drinkName,c.category,g.glassware,b.IBA,d.addedInfo,d.imagePath,d.instructions
)
SELECT a.*,dtm.tags
FROM a
JOIN (select
drinkID,string_agg(t.tag,') as tags
from tags t
join tagmap tm on tm.tagID = t.id
group by drinkID) as dtm
ON a.ID = dtm.drinkID