SQL Server – 比较所有可能的组合并将结果保存在另一个表中

huangapple go评论60阅读模式
英文:

Sql server - comparison of all possible combinations and saving the result in another table

问题

我有一个简单的SQL查询,询问一个对象是否具有指定的特征。
举个简单的例子,我想要检查一组对象是否是双色、三色、四色的。所以我有可变的特征(取决于外部用户),在这个例子中,用户选择了颜色:红色('C1')、黄色('C2')、绿色('C3')、蓝色('C4')。他想知道是否有红-黄、红-绿、红-蓝...红-黄-绿...红-黄-蓝-绿(任何组合)的对象。

我的代码则分别查找具有共同特征的对象:

"SELECT [Object] FROM TableData WHERE [character A] = '" + C1 + "' INTERSECT SELECT [Object] FROM TableData WHERE [character A] = '" + C2 + "'";

接下来是:

"SELECT [Object] FROM TableData WHERE [character A] = '" + C1 + "' INTERSECT SELECT [Object] FROM TableData WHERE [character A] = '" + C3 + "'";

...

然后,我必须将所有找到的对象保存到一个新表中,为它们创建两个新的特定值:

  • 对象正在寻找的颜色数量
  • 识别颜色的类别(例如'C12' - 在给定情况下识别红-黄)

我的C#代码如下:

string sqlStatement = "INSERT INTO AnalysisTable (Colors, Object, level) VALUES (@val1,@val2,@val3)";
try
{
    con.Open();
    SqlCommand cmd = new SqlCommand(sqlStatement, con);
    cmd.Parameters.Clear();
    cmd.Parameters.AddWithValue("@val1", "C12");
    cmd.Parameters.AddWithValue("@val2", C12[i].Object);
    cmd.Parameters.AddWithValue("@val3", "2");
    cmd.ExecuteNonQuery();
}

我逐个检查每种组合。这会生成大量的代码,我相信可以以某种方式简化...但我不知道如何做。

提前感谢您的任何帮助。

附:如果对象是红-黄-绿的,应该保存四次:

  1. 红-黄
  2. 红-绿
  3. 黄-绿
  4. 红-黄-绿

编辑:简化的结构:链接

在尝试简化代码时,遇到了“子查询返回多个值”的问题。我的核心代码避免了这个问题,因为它首先获取了单独查询的值,然后将它们添加在一起。我找不到解决方法。

为了更好地解释,程序代码在指定特征后比较数据集。

英文:

I have a simple sql query that asks if an object has the specified characteristics.
For simple example, I want to check if a group of objects is a double, triple, quadra color. And so I have variable characteristics (depending on the external user), in this example the user has chosen the colors: red ('C1'), yellow ('C2'), green ('C3'), blue ('C4'). And he wants to know if there are objects of red-yellow, red-green, red-blue ... red-yellow-green ... red-yellow-blue-green (any combination).

My code, in turn (in separate queries), looks for objects with common characteristics:

"SELECT [Object] FROM TableData WHERE [character A] = '" + C1 + "' INTERSECT SELECT [Object] FROM TableData WHERE [character A] = '" + C2 + "'";

next

"SELECT [Object] FROM TableData WHERE [character A] = '" + C1 + "' INTERSECT SELECT [Object] FROM TableData WHERE [character A] = '" + C3 + "'";

...

and then I have to save all found objects to a new table creating two new specific values for them

  • how many colors the object is looking for
  • category identifying colors (for example 'C12' - identifying red-yellow in a given case)

my code in C#

string sqlStatement = "INSERT INTO AnalysisTable (Colors, Object, level) VALUES (@val1,@val2,@val3)";
                            try
                            {
                                con.Open();
                                SqlCommand cmd = new SqlCommand(sqlStatement, con);
                                cmd.Parameters.Clear();
                                cmd.Parameters.AddWithValue("@val1", "C12");
                                cmd.Parameters.AddWithValue("@val2", C12[i].Object);
                                cmd.Parameters.AddWithValue("@val3", "2");
                                cmd.ExecuteNonQuery();
                            }

I check each combination one by one. It generates a lot of code and I'm sure it can be simplified somehow...
But i don't know how

Thanks in advance for any help

Ps. if object is red-yellow-green should save it four times as

  1. red-yellow
  2. red-green
  3. yellow-green
  4. red-yellow-green

Edit
simplified structure
https://dbfiddle.uk/8oUNkVdZ

In my attempts to simplify the code the problem is 'Subquery returned more than 1 value'. My core code gets around this because it fetches the values for a separate query first and then adds them. I couldn't find a workaround.

For a better explanation, the program code compares datasets after point specifying character.

答案1

得分: 1

也许这个任务更适合使用递归来解决。我将提供一个更简单(直接)的解决方案。
尝试这个。不使用临时表。

with colors2 as (
  select c1, c2 from (values('white', 'black'), ('white', 'green'), ('white', 'red'),
                     ('black', 'green'), ('black', 'red'), ('green', 'red')
                    ) t(c1, c2)
),
colors3 as (
  select c1, c2, c3 from (values('white', 'black', 'green'), ('white', 'black', 'red'),
                          ('white', 'green', 'red'), ('black', 'green', 'red')
                    ) t(c1, c2, c3)
),
colors4 as (
  select c1, c2, c3, c4 from (values('white', 'black', 'green', 'red')
                    ) t(c1, c2, c3, c4)
),
t2 as (
select [object]
  ,string_agg([character A], ',') colors
from TableData
group by [Object]
)
select object, c1, c2, '' c3, '' c4, colors  
from t2 t
left join colors2 t2 on charindex(t2.c1, t.colors) > 0 and charindex(t2.c2, t.colors) > 0
where c1 is not null
union all
select object, c1, c2, c3, '' c4, colors  
from t2 t
left join colors3 t3 on charindex(t3.c1, t.colors) > 0 and charindex(t3.c2, t.colors) > 0
     and charindex(t3.c3, t.colors) > 0
where c1 is not null
union all
select object, c1, c2, c3, c4, colors  
from t2 t
left join colors4 t4 on charindex(t4.c1, t.colors) > 0 and charindex(t4.c2, t.colors) > 0
     and charindex(t4.c3, t.colors) > 0 and charindex(t4.c4, t.colors) > 0
where c1 is not null
order by [Object]

查询结果:

object c1 c2 c3 c4 colors
Object1 white black red,white,green,black
Object1 white green red,white,green,black
Object1 white red red,white,green,black
Object1 black green red,white,green,black
Object1 black red red,white,green,black
Object1 green red red,white,green,black
Object1 white black green red,white,green,black
Object1 white black red red,white,green,black
Object1 white green red red,white,green,black
Object1 black green red red,white,green,black
Object1 white black green red red,white,green,black
Object2 green red red,green
Object3 white red white,red

可以简单地排除具有null的对。

英文:

May be this task better solved by reсursion. I will offer a simpler (direct) solution.
Try this. Temporary table not used.

with colors2 as(
  select c1,c2 from (values('white','black'),('white','green'),('white','red')
                       ,('black','green'),('black','red')
                       ,('green','red')
                    )t(c1,c2)
)
,colors3 as(
  select c1,c2,c3 from (values('white','black','green'),('white','black','red')
                          ,('white','green','red')
                          ,('black','green','red')
                    )t(c1,c2,c3)
)
,colors4 as(
  select c1,c2,c3,c4 from (values('white','black','green','red')
                    )t(c1,c2,c3,c4)
)

,t2 as(
select [object]
  ,string_agg([character A],',') colors
from TableData
group by [Object]
)
select object,c1,c2,'' c3,'' c4,colors  
from t2 t
left join colors2 t2 on charindex(t2.c1,t.colors)>0 and charindex(t2.c2,t.colors)>0
where c1 is not null
union all
select object,c1,c2,c3,'' c4,colors  
from t2 t
left join colors3 t3 on charindex(t3.c1,t.colors)>0 and charindex(t3.c2,t.colors)>0
     and charindex(t3.c3,t.colors)>0
where c1 is not null
union all
select object,c1,c2,c3,c4,colors  
from t2 t
left join colors4 t4 on charindex(t4.c1,t.colors)>0 and charindex(t4.c2,t.colors)>0
     and charindex(t4.c3,t.colors)>0 and charindex(t4.c4,t.colors)>0
where c1 is not null
order by [Object]

Query result

object c1 c2 c3 c4 colors
Object1 white black red,white,green,black
Object1 white green red,white,green,black
Object1 white red red,white,green,black
Object1 black green red,white,green,black
Object1 black red red,white,green,black
Object1 green red red,white,green,black
Object1 white black green red,white,green,black
Object1 white black red red,white,green,black
Object1 white green red red,white,green,black
Object1 black green red red,white,green,black
Object1 white black green red red,white,green,black
Object2 green red red,green
Object3 white red white,red

Pairs with null may be excluded simply.

Example, based on your fiddle

huangapple
  • 本文由 发表于 2023年7月12日 21:06:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76670909.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定