可以扩展 x 数量的选项和值组合的查询

Posted

技术标签:

【中文标题】可以扩展 x 数量的选项和值组合的查询【英文标题】:Query that can scale for x amount of options & values combinations 【发布时间】:2018-02-02 06:21:23 【问题描述】:

试图返回每辆汽车的每个选项值组合的结果,但在理解如何做时遇到了一些麻烦。

这是所涉及的表的结构和所需的结果。我在网上找到的唯一一件事是关于使用交叉连接,但在这种情况下,选项维度的数量是未知的,所以这不会像我预期的那样工作。

请参阅下面所需的结构/结果:

我熟悉使用 STUFF() FOR XML,因此将它们组合起来不是问题,但问题是找到它将正确返回值以进行定义的查询。

【问题讨论】:

您的数据让我有些困惑。目前尚不清楚生成输出的逻辑是什么。 图片已更新,更有意义 您提到特征的数量(例如颜色、年份)是任意的。这意味着您需要每个品牌的特征的 n 维笛卡尔积。这使得这个问题成为this 的欺骗和(以更现代的风格)我即将投票关闭的问题... Cross join N sets of rows in same table的可能重复 问题是,该链接的答案表明这些名称是已知的。在这种情况下,它们可以是动态的/未知的。 【参考方案1】:

检查这个查询

with myTable as (
    select
        *
    from
        (values
            ('BMW','COLOR','Black')
            ,('BMW','COLOR','Red')
            ,('BMW','COLOR','Blue')
            ,('BMW','YEAR','2010')
            ,('BMW','YEAR','2011')
            ,('Ferrari','COLOR','Yellow')
            ,('Ferrari','COLOR','White')
            ,('Ferrari','YEAR','2012')
            ,('Ferrari','YEAR','2013')
        ) t(car, name, value)
)

select
    a.car, a.value + ' ' + b.value
from
    myTable a
    join myTable b on a.car = b.car and a.name <> b.name
where
    a.name = 'COLOR'
    and b.name = 'YEAR'

【讨论】:

维数未知怎么办?所以查询应该返回任意数量的维度.. 颜色、年份、英里、最高速度等 - 未知.. 如果不知道dimesions 的数量,您将不知道需要多少表连接。所以,我认为在这种情况下你需要动态 SQL 对,但是在这种情况下有没有办法避免动态sql? 目前我认为这是不可能的。如果我能找到这样的方法,我会告诉你的【参考方案2】:

请试试这个。

Declare @CAR AS TABLE 
    (
     car varchar(100),
     name varchar(100),
     value varchar(100)
    )

    insert into @CAR 
     values
                ('BMW','COLOR','Black')
                ,('BMW','COLOR','Red')
                ,('BMW','COLOR','Blue')
                ,('BMW','YEAR','2010')
                ,('BMW','YEAR','2011')
                ,('Ferrari','COLOR','Yellow')
                ,('Ferrari','COLOR','White')
                ,('Ferrari','YEAR','2012')
                ,('Ferrari','YEAR','2013')

    Select b.car,a.value + ' ' + b.value as value from @CAR b RIGHT OUTER JOIN (
    Select car,name,value as value from @CAR where name='COLOR') as a on a.car = b.car and b.name='YEAR'

【讨论】:

【参考方案3】:

试试下面的查询,这里使用了CTE。我只是使用前 3 或 4 个 CTE 来生成主数据,您可以根据您的表结构更改它。

WITH AUTOMOBILES
AS  (
    SELECT 1 ID,'BMW M3' Name
    UNION
    SELECT 2,'Ferrari F 430'
), OPTIONS
AS  (
    SELECT 1 ID,'Color' Name
    UNION
    SELECT 2,'Year'
    UNION
    SELECT 3,'Top Speed'
),AM_VALUES
AS  (
    SELECT 1 ID,1 AutomobileID,1 OptionID,'Black' Value
    union
    select 2,1,1,'Red'
    union
    select 3,1,1,'Blue'
    union
    select 4,1,2,'2010'
    union
    select 5,1,2,'2011'
    union
    select 6,2,1,'Yellow'
    union
    select 7,2,1,'white'
    union
    select 8,2,2,'2012'
    union
    select 9,2,2,'2013'
    union
    select 10,2,3,'Sp210'
    union
    select 11,2,3,'Sp190'
),INPUT_TABLE
AS  (
SELECT  V.ID,V.AutomobileID,A.Name Car,V.OptionID,O.Name, V.Value
        ,DENSE_RANK() OVER(PARTITION BY V.AutomobileID ORDER BY  V.OptionID ) AS OptionRowNo
FROM    AM_VALUES   AS  V
    INNER JOIN AUTOMOBILES  AS  A   ON  A.ID    =   V.AutomobileID
    INNER JOIN OPTIONS      AS  O   ON  O.ID    =   V.OptionID
),VTREE
AS  (
    SELECT  DISTINCT AutomobileID,ID AS Node,NULL AS Parent,OptionRowNo,CAST(Value AS nvarchar) AS Value,1 RowNo
    FROM    INPUT_TABLE
    WHERE   OptionRowNo     =   1
    UNION ALL

    SELECT  V.AutomobileID,I.ID,V.Node,I.OptionRowNo,CAST(V.Value+' '+I.Value AS nvarchar),RowNo=RowNo+1
    FROM    VTREE   AS  V
        INNER JOIN  INPUT_TABLE AS  I   ON  I.AutomobileID  =   V.AutomobileID
                                        AND I.OptionRowNo   >   V.OptionRowNo
)

SELECT  AutomobileID,Value
FROM    VTREE AS V
WHERE   RowNo =     (   SELECT TOP 1 COUNT(DISTINCT I1.OptionID) 
                        FROM INPUT_TABLE AS I1 
                        WHERE I1.AutomobileID = V.AutomobileID
                        GROUP BY I1.AutomobileID)
ORDER BY AutomobileID,Value

输出:-

AutomobileID    Value
1               Black 2010
1               Black 2011
1               Blue 2010
1               Blue 2011
1               Red 2010
1               Red 2011
2               white 2012 Sp190
2               white 2012 Sp210
2               white 2013 Sp190
2               white 2013 Sp210
2               Yellow 2012 Sp190
2               Yellow 2012 Sp210
2               Yellow 2013 Sp190
2               Yellow 2013 Sp210

【讨论】:

以上是关于可以扩展 x 数量的选项和值组合的查询的主要内容,如果未能解决你的问题,请参考以下文章

如何计算明细表中的唯一组合?

在一个 Power Query 中合并多个工作簿中的相同选项卡

创建表格的最佳方式,其中包含产品选项和版本的每种可能组合

您可以使用啥属性和值来使 <a> 元素在新的浏览器选项卡中打开链接? [复制]

java项目中如何实现多选项的模糊或者精确查询

java项目中如何实现多选项的模糊或者精确查询