比较2个没有INTERSECT的结果集

时间:2015-05-24 09:17:18

标签: sql sql-server-ce

我有两张桌子: -

ITEM(ITEM_ID, ITEM_NAME)

STATS(ITEM_ID, STAT_ID, STAT_VALUE)

我想将ITEM_IDsSTATS完全相同,但它位于SQL Server Compact上(无EXCEPTINTERSECT

例如:

STATS:-
1 12 100 
1 13 500
2 12 200
2 14 300
3 12 100
3 13 500
4 12 100

应该返回1和3的行(相同的统计数据/值12/100和13/500)

没有INTERSECT可以吗?

5 个答案:

答案 0 :(得分:4)

在ITEM表中使用内部联接,并在条件上使用您希望在该表上看到的任何内容

答案 1 :(得分:3)

第一次我完全错了: - )

找到相同集合的标准方法"很难理解,大表通常表现不好,因为它们涉及将所有内容与其他所有内容进行比较(类似于CROSS JOIN)。

AFAIK SQL Server CE也支持XML函数,因此最好的方法是Vladimir Baranov在现有答案中描述的那个:

with cte as
 ( -- group concat all rows for one ITEM_ID into one big string
   SELECT distinct ITEM_ID,
     (select '#' + rtrim(STAT_ID) + ',' + rtrim(STAT_VALUE) 
      from STATS as t2 
      where t1.ITEM_ID = t2.ITEM_ID ORDER BY STAT_ID FOR XML PATH('') ) as rowsConcat
   FROM STATS as t1
 ),
cnts as
 ( -- how many rows exist for that concatenated string?
   select *
     ,count(*) 
      over (partition by rowsConcat) as cnt
   from cte
 ) 
select ITEM_ID
  ,dense_rank() -- assign the same group number to the duplicates 
   over(order by rowsConcat) as duplicateGroup
from cnts
where cnt > 1 -- more than one

fiddle

答案 2 :(得分:3)

以下是我将如何处理此类任务。

第1步。拥有一个函数/方法,可将多列中的值合并为一列。在您的情况下,我们希望将两个值STAT_IDSTAT_VALUE放在一起。在这种情况下,简单转换为字符串和连接就足够了。所以,有两列的行:

STAT_ID STAT_VALUE
12      100 

成为一列有一列:

single_value
12_100

此转换的结果应该是这样的表:

ITEM_ID single_value
1       12_100 
1       13_500
2       12_200
2       14_300
3       12_100
3       13_500
4       12_100

第2步。有一些Aggregate函数接受多行中的值,并返回一个值作为长连接字符串。它可以是CLR函数,T-SQL函数或FOR XML构造。您可以根据SQL Server CE支持的内容选择一个。

此转换的结果应该是这样的表:

ITEM_ID aggregated_single_value
1       12_100__13_500
2       12_200__14_300
3       12_100__13_500
4       12_100

第3步。获得此结果后,您只需GROUP BY aggregated_single_valueCOUNT有多少ITEM_IDs具有完全相同的值集。然后,只返回ITEM_IDs计数超过1的HAVING

aggregated_single_value  Count
12_100__13_500           2
12_200__14_300           1
12_100                   1

修改

整体方法仍然适用于SQL Server CE的限制。

  • 它没有Common-Table-Expressions - 为每一步使用显式临时表。
  • 它没有FOR XML,用户定义的函数,CLR - 手动进行聚合"。它看起来像supports cursors。打开光标 - 使用正确的顺序扫描表格,聚合值并将它们保存到临时表格。
  • 它是否支持varbinary(max)varchar(max)等大型类型?如果是 - 很好,如果不是 - 您将被限制为varchar(8000)varbinary(8000)。如果ITEM_ID表中的同一STATS最多有两行(或大约),则8000字节就足够了。

此外,至少有一种简单粗略的方法来限制游标处理的行数。首先对ITEM_ID表中的每个STATS执行简单的行计数,并仅保留具有匹配计数的IDs行。换句话说,过滤掉明显的不匹配。此步骤将从您的示例中删除ID=4

答案 3 :(得分:2)

我不确定SQL Server Compact是否支持内部查询,但这个概念应该有效:

select distinct a.item_id 
       from  stats a 
       where exists(select 1 
                           from stats b 
                           where a.stat_d=b.stat_id 
                            and a.stat_value=b.stat_value)

答案 4 :(得分:2)

  

<强> procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin // here some code end; procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin // more code here end; procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin // here other code end;
  返回INTERSECT操作数左侧和右侧的查询返回的任何不同值。

使用INTERSECT的替代方法是使用INTERSECT,如下所示:

JOIN

等于

SELECT A.*
FROM A   -- [A: ID, Name]
INTERSECT
SELECT B.*
FROM B  -- [B: ID, Name]

或使用SELECT DISTINCT A.* FROM A JOIN ( SELECT B.* FROM B) B1 ON A.ID = B1.ID AND A.Name = B1.Name

EXISTS

尝试此查询:

SELECT DISTINCT A.*
FROM A
WHERE EXISTS (
    SELECT 1 
    FROM B WHERE A.ID = B.ID AND A.Name = B.Name)