【问题标题】:Find valid combinations based on matrix根据矩阵查找有效组合
【发布时间】:2016-03-11 21:29:03
【问题描述】:

我在 CALC 中有一个以下矩阵:第一行 (1) 包含员工编号,第一列 (A) 包含产品代码。 上面的相应员工出售的产品项目到处都有一个 X

     | 0302  |  0303 | 0304 | 0402 |
1625 |  X    |       |   X  |   X  |
1643 |       |    X  |   X  |      |
...

我们看到产品 1643 由员工 0303 和 0304 销售

我希望看到的是哪些产品由哪些员工销售但格式如下的列表:

1625 | 0302, 0304, 0402 |
1643 | 0303, 0304 |

这样做的原因是我们需要这个矩阵最终导入到 SQL SERVER 表中。我们无法访问该矩阵的起源。它包含大约 50 名员工和 9000 多种产品。

感谢您与我们一起思考!

【问题讨论】:

    标签: sql-server tsql ssis libreoffice calc


    【解决方案1】:

    试试这样的

    ;with data as
    (
    SELECT *
    FROM   ( VALUES (1625,'X',NULL,'X','X'),
                    (1643,NULL,'X','X',NULL))
             cs (col1, [0302], [0303], [0304], [0402]) 
    ),cte
         AS (SELECT col1,
                    col
             FROM   data
                    CROSS apply (VALUES ('0302',[0302]),
                                        ('0303',[0303]),
                                        ('0304',[0304]),
                                        ('0402',[0402])) cs (col, val)
             WHERE  val IS NOT NULL)
    SELECT col1,
           LEFT(cs.col, Len(cs.col) - 1) AS col
    FROM   cte a
           CROSS APPLY (SELECT col + ','
                        FROM   cte B
                        WHERE  a.col1 = b.col1
                        FOR XML PATH('')) cs (col)
    GROUP  BY col1,
              LEFT(cs.col, Len(cs.col) - 1) 
    

    【讨论】:

    • 我明白你的意思。然而,为此所需的工作量可能很大。 (请记住,有 50 多名员工)。但我将对此进行测试,因为它真的很巧妙。所以你(至少)应该得到支持 :) 如果我能让它发挥作用,我会将其标记为答案并解释我是如何做事的
    • 我在sql中创建了一个表来保存数据:
    • @Henrov - 很高兴它帮助了你
    • 如果我想查找员工和产品代码的所有组合怎么办?因此,使用上面的示例,我将如何在 productitem、employee# --> 1625,0302 1625,0302 1625,0402 1643,0303 1643,0304 等两列中获得输出?没关系,只是划掉了 XML 子句。。应该马上就看到了。。
    【解决方案2】:

    我认为有两个问题需要解决:

    1. 获取X 标记的产品代码;
    2. 将它们连接成一个以逗号分隔的字符串。

    我无法一次性为这两个问题提供解决方案,但您可以分别处理这两个问题。

    1.

    要将X 标记替换为相应的产品代码,您可以使用数组函数创建第二个表(矩阵)。为此,请创建一个新工作表,复制第一列/第一行,然后在单元格 B2 中输入以下公式:

    =IF($B2:$E3="X";$B$1:$E$1;"")
    

    您必须调整公式,以便它涵盖您的完整输入数据(如果您的最后一个数据单元格是 Z9999,它将是 =IF($B2:$Z9999="X";$B$1:$Z$1;""))。我的示例仅涵盖两行四列。

    修改后,CTRL+SHIFT+ENTER确认将其应用为数组公式

    2.

    现在,您必须连接产品代码。 LO Calc 缺少连接数组的功能,但您可以使用简单的用户定义函数。对于这样的字符串连接函数,请参阅this answer。只需使用那里提供的 StarBasic 代码创建一个新宏并保存即可。现在,您手头有一个 STRJOIN() 函数,它接受一个数组并将其值连接起来,将空值排除在外。

    您可以使用第二张工作表上的帮助列添加该功能,并通过将其向下拖动来应用它。最后,要删除具有单个产品 ID 的单元格,请复制完整的第二张表,粘贴特殊到第三张表中,仅粘贴值。现在,您可以删除除第一列(员工 ID)和最后一列(带有连接的产品 ID)之外的所有列。

    【讨论】:

      【解决方案3】:

      我在 sql 中创建了一个表来保存数据:

      CREATE TABLE [dbo].[mydata](
          [prod_code] [nvarchar](8) NULL,
          [0100] [nvarchar](10) NULL,
          [0101] [nvarchar](10) NULL,
          [and so on...]
      

      我通过复制和粘贴转置的方式在 Calc 中创建了列列表。之后,我使用 concatenate 函数为 create table 语句创建 columnlist + 数据类型

      我清理了工作表并使用 SQL Server 的导入向导将其导入到此表中。清理意味着删除不必要的行/列。由于列名相同,99% 的映射正确完成。 现在我有了 SQL Server 中的数据。

      我修改了 MM93 建议的代码:

      ;with data as
      (
      SELECT *
      FROM   dbo.mydata  <-- here i simply referenced the whole table
      ),cte
      

      在下一部分中,我使用相同的“工作表”技巧来列出和格式化所有列名并将它们粘贴进去。

      ),cte
           AS (SELECT prod_code, <-- had to replace col1 with 'prod_code' 
                      col
               FROM   data
                      CROSS apply (VALUES ('0100',[0100]),
                                  ('0101', [0101] ),
                                  (and so on... ),
      

      这个查询的结果被插入到一个新表中,我和我的同事正在查询我们的 harts :)

      PS:删除“FOR XML”子句会导致表格包含两列:

      prodcode | employee
      

      其中包含prodcode + employeenumber 的所有独特组合,查询起来更快更实用。

      【讨论】:

      • 如果您不想键入 so on 部分,可以使用动态 sql
      • @MM93 我今晚会试试,现在我很高兴有你的帮助。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-14
      • 2020-04-30
      • 2014-06-25
      • 2014-12-02
      • 2019-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多