从多个表中获取类似的列名和计数

时间:2017-11-08 02:07:47

标签: sql sql-server

所以我有一张名为“SongsMetadata'在我的数据库中有6列,如下所示(appx 70k记录)。它包含所有与歌曲相关的信息。

SongsMetadata Table

与常规数据库表略有不同。 ' File_name'列包含.csv文件。这些是实际的表,它们前面的值是该csv文件中的列。

所以对于' 1001186_1_7562755270480253254.csv'记录在SongsMetadata表中,' 1001186_1_7562755270480253254'是表格名称,它的列是'&#n;',' name',' album',' time', '价格' (这些表包含大量垃圾值)

我的目标是比较所有表(在本例中为.csv文件)以获取所有类似的列名及其计数。现在我已经有了一个解决方案来获取常用列名并计算普通表here。每个表格将与其他表格进行比较。但是,我不确定如何使用.csv表实现相同的效果。

预期输出为:

1001186_1_7562755270480253254.csv & 1001186_0_5503858345485431752.csv | &nbsp, name, price| 3 #common columns count
1001186_0_5503858345485431752.csv & 99524146_0_3894874701785592836.csv | &nbsp, name, price| 3
and so on...

任何建议都表示赞赏。

1 个答案:

答案 0 :(得分:0)

以下解决方案显示了如何处理您的exsting表,以便有效地进行所需匹配。这需要unpivot,尽管使用cross apply和{{1}执行了unpivot的效果这是一种简单有效的方法。之后"匹配"显示,然后是另一个查询细节,你也可能觉得有用。最后,显示新表只是为了帮助可视化它是什么。

SQL Fiddle

上查看现场演示

小样本

values

UNPIVOT查询

此查询将列信息移动到规范化结构中,以便进行后续匹配。这对整体解决方案至关重要。作为额外的奖励,您可以将一些列名称标记为" bad"以便稍后可以忽略这些,例如CREATE TABLE SongsMetadata ([file_name] varchar(7), [col1] varchar(6), [col2] varchar(6), [col3] varchar(6), [col4] varchar(6)) ; INSERT INTO SongsMetadata ([file_name], [col1], [col2], [col3], [col4]) VALUES ('abc.csv', ' ', 'name', 'price', 'artist'), ('def.csv', 'name', ' ', ' ', 'price') ; (最有可能是垃圾数据)

 

查询1

这是"匹配逻辑"在http://rextester.com/TLQ28814处提供但适用于不透明的歌曲数据,并且它可以排除您根本不想考虑的列名(col_is_good)。

select
    file_name, column_number, column_name
    , case when column_name IN ('&nbsp;','</b>','other-unwanted') then 0 else 1 end as col_is_good
    into SongsMetadataUpivot
from (
    select file_name, column_number, column_name
    from SongsMetadata
    cross apply (
          values
               (1, col1)
             , (2, col2)
             , (3, col3)
             , (4, col4)
         ) ca (column_number, column_name)
     ) d
;

<强> Results

with fmatch as (
    select 
        l.file_name + ' & ' + r.file_name AS comparing_files
      , l.column_name
    from SongsMetadataUpivot l
    inner join SongsMetadataUpivot r on l.column_name = r.column_name
                                    and l.file_name < r.file_name
                                    and r.col_is_good = 1
    where l.col_is_good = 1
    ) 
select --* from fmatch
      f.comparing_files
    , STUFF((
            SELECT
                  N', ' + column_name
            FROM fmatch c
            WHERE f.comparing_files = c.comparing_files
            order by c.column_name
            FOR xml PATH (''), TYPE
      )
      .value('text()[1]', 'nvarchar(max)'), 1, 2, N'') as columns
  , count(*) as num_col_matches
from fmatch f
group by f.comparing_files

查询2

这将只允许按名称顺序生成列列表以及每个文件中各自的列位置。

|   comparing_files |     columns | num_col_matches |
|-------------------|-------------|-----------------|
| abc.csv & def.csv | name, price |               2 |

<强> Results

SELECT
     file_name, ca.*
from SongsMetadata f
cross apply (
  select
      STUFF((
            SELECT
                  N', ' + column_name
            FROM SongsMetadataUpivot c
            WHERE f.file_name = c.file_name
            AND c.col_is_good = 1
            ORDER BY column_name
            FOR xml PATH (''), TYPE
      )
      .value('text()[1]', 'nvarchar(max)'), 1, 2, N'')
    , STUFF((
            SELECT
                  N', ' + cast(column_number as nvarchar)
            FROM SongsMetadataUpivot c
            WHERE f.file_name = c.file_name
            AND c.col_is_good = 1
            ORDER BY column_name
            FOR xml PATH (''), TYPE
      )
      .value('text()[1]', 'nvarchar(max)'), 1, 2, N'')
   ) ca (column_names, col_numbers)

查询3

因此,您可以想象出&#34; unpivoted&#34;数据,整体解决方案需要这样做。

| file_name |        column_names | col_numbers |
|-----------|---------------------|-------------|
|   abc.csv | artist, name, price |     4, 2, 3 |
|   def.csv |         name, price |        1, 4 |

<强> Results

select * from SongsMetadataUpivot