0

我有 3 张桌子:

Silk_Skey   Name
1   Black White Checks Yellow Arms
2   Black Crimson Stripes
3   Crimson Yellow Stripes

Sub Colour  Major Colour
Black   Black
White   White
Yellow  Yellow
Crimson Red

MajorColour_Skey    Major Colour
1   Black
2   White
3   Yellow
4   Red

我想实现这一点:

ID  Silk_Skey   MajorColour_Skey
1   1   1
2   1   2
3   1   3
4   2   1
5   2   4
6   3   3
7   3   4

我需要做的是创建一个与 3 个表中的所有颜色匹配的链接表,并分解丝绸名称,以便在新表中显示 4 行)见下面的 SQL。我的老板建议我使用“IS IN”查询,但我不知道那是什么,你能帮忙吗?

SELECT s.Silks_Skey, mc.MajorColour_Skey
FROM Silks s  INNER JOIN SubColour sc  on sc.SubColour **'IS IN HERE'** s.SilksName
INNER JOIN MajorColour mc
ON sc.MajorColour = mc.MajorColour
4

5 回答 5

3

您可以使用IN

AND table.column IN ('a','b','c')

或者

AND table.column IN (1,2,3)

或者如果你正在寻找一个你可以做的字符串

AND table.column LIKE '%word'  -- table.column ends with 'word'
AND table.column LIKE 'word%'  -- table.column starts with 'word'
AND table.column LIKE '%word%' -- table.column has 'word' anywhere in the column
于 2013-05-01T14:37:26.920 回答
1

对于您想要做的事情,您需要进行字符串操作,因为您试图将一种颜色与字符串中的颜色列表进行比较。

like操作员可以做到这一点。试试这个on子句:

on ' '+ s.SilksName +' ' like '% '+sc.SubColour+' %'

sc.SubColour这将检查列表 ( ) 中是否存在给定颜色 ( s.SilksName)。例如,如果您有一个类似“RED GREEN”的列表,它将匹配“%RED%”或“%GREEN%”。

连接空格的目的是避免部分单词匹配。例如,“blue-green”将匹配“blue”和“green”而没有分隔符。

以下查询返回 7 行,这似乎是正确的(丝绸中的第一行 3 行,其他两行各 2 行):

with silks as (
      select 1 as silks_skey, 'Black White Checks Yellow Arms' as silksname union all
      select 2, 'Black Crimson Stripes' union all
      select 3, 'Crimson Yellow Stripes'
     ),
     subcolour as (
      select 'black' as subcolour, 'black' as majorcolour union all
      select 'white', 'white' union all
      select 'yellow', 'yellow' union all
      select 'crimson', 'red'
     ),
     MajorColour as (
      select 1 as MajorColour_skey, 'black' as MajorColour union all
      select 2, 'white' union all
      select 3, 'yellow' union all
      select 4, 'red'
     )
SELECT s.Silks_Skey, mc.MajorColour_Skey
FROM Silks s  INNER JOIN SubColour sc  on ' ' + s.SilksName + ' ' like '% ' + sc.SubColour + ' %'
INNER JOIN MajorColour mc
ON sc.MajorColour = mc.MajorColour
于 2013-05-01T14:38:17.447 回答
1

这是一种注定性能不佳、编写查询笨拙和痛苦的设计。如果你的数据库永远不会很大,那么它可能是可行的,但如果它会很大,你就不能使用这种设计结构并希望有良好的性能,因为你将无法正确使用索引。我个人会添加一个与丝绸表相关的丝绸颜色表,并单独存储颜色。数据库设计的首要规则之一是永远不要在一个字段中存储多个信息。您正在存储一个列表,这始终意味着您需要一个相关表才能有效使用数据库。

一个糟糕的(并且随着时间的推移通常不可行)数据库设计的一个线索是,您是否需要使用任何类型的函数或计算来连接,或者您是否需要在 like 子句的短语开头使用通配符。现在解决这个问题,事情会变得更加顺利,维护将花费更少的时间并且性能会更好。你目前的结构没有任何好处。

您可能需要花费一些额外的时间来按单个颜色解析和存储丝绸名称,但是您在查询数据库中节省的时间将非常重要,因为您现在可以使用连接然后使用索引。搜索 fn_split,您将看到一种将丝绸名称拆分为单独颜色的方法,您可以在插入记录时使用这些颜色。

如果您愚蠢地决定保留当前结构,请考虑使用全文搜索。它比使用带有通配符作为第一个字符的 like 子句要快。

于 2013-05-01T14:57:32.937 回答
0

这就是答案,感谢您的所有想法。

Select S.[Silks_Skey], MC.[MajorColour_Skey] 
from [dbo].[Silks] S 
inner join [dbo].[SubColour] SC on CHARINDEX(SC.[SubColour],S.[SilksName]) <> 0
inner join [dbo].[MajorColour] MC on SC.[MajorColour] = MC.[MajorColour]

UNION ALL

Select S.[Silks_Skey], MC.[MajorColour_Skey] 
from [dbo].[Silks] S 
inner join [dbo].[MajorColour] MC on CHARINDEX(MC.[MajorColour],S.[SilksName]) <> 0

ORDER BY S.[Silks_Skey]
于 2013-05-02T08:37:04.547 回答
0

听起来您真正想要做的是将Name字段拆分为空格,然后对于包含在颜色表中的每个值(加入子颜色,因为主要颜色也是有效的子颜色)您想要一个新表中的条目。问题是没有用于拆分字符串的内在 T-SQL 函数。要做到这一点,最好的办法是访问Erland Sommarskog关于如何做到这一点的明确答案。

另一种方法是在您的谓词中使用 CONTAINS 关键字,这种方法不是很整洁并且可能有效也可能无效。然而,为了实现这一点,您需要使用全文索引,我怀疑使用 Erland 在 SQL 中拆分字符串和数组的优秀指南会更合适和更快。

于 2013-05-01T15:14:17.507 回答