提取所有行的sql server查询

to94eoyn  于 2021-07-29  发布在  Java
关注(0)|答案(2)|浏览(353)

我有两个数据库表,一个叫做“headers”,另一个叫做“rows”。结构为:

Header: IDPK | Description
Row:    IDPK | IDPK_Header | Item_ID | Qty

我需要做一个查询:“从一个标题,idpk找到另一个标题有相同的行数和相同的项目id和数量”。
例如:

Header             Rows
IDPK  Description  IDPK    Item_ID    Qty
 1    'Test1'       1        'A'      10
 1    'Test1'       2        'B'      20
 2    'Test2'       3        'A'      10
 2    'Test2'       4        'B'      20
 3    'Test3'       5        'A'      5
 3    'Test3'       6        'B'      20
 4    'Test4'       7        'A'      10

收割台 Test1 匹配 Test2 但不是 Test3 以及 Test4 问题是行数必须完全相同。我试着 ALL 但运气不好。
我怎样才能用对性能的观察来进行查询?这两个表可能非常大(约50万条记录)。

pqwbnv8z

pqwbnv8z1#

我建议使用forxml查询来创建每个idpk的项目列表。接下来我将搜索匹配的项目列表和数量。参见以下示例:

DECLARE @Headers TABLE(
IDPK INT,
Description NVARCHAR(100)
)

DECLARE @Rows TABLE(
IDPK INT,
ITEMID NVARCHAR(1),
Qty INT
)

INSERT INTO @Headers VALUES
(1, 'Test1'),
(2, 'Test2'),
(3, 'Test3'),
(4, 'Test4'),
(5, 'Test5')

INSERT INTO @Rows VALUES
 (1, 'A', 10),
 (1, 'B', 20),
 (2, 'A', 10),
 (2, 'B', 20),
 (3, 'A', 5 ),
 (3, 'B', 20),
 (4, 'C', 10),
 (5, 'A', 10),
 (5, 'C', 20)
;

WITH cteHeaderRows AS(
  SELECT IDPK
        ,ItemIDs=STUFF(  
                        (  
                          SELECT ',' + CAST(ITEMID AS VARCHAR(MAX))  
                            FROM @Rows t2   
                            WHERE t2.IDPK = t1.IDPK 
                            ORDER BY ITEMID, QTY  
                            FOR XML PATH('')  
                        ),1,1,''  
                      )
        ,Qtys=STUFF(  
                        (  
                          SELECT ',' + CAST(Qty AS VARCHAR(MAX))  
                            FROM @Rows t2   
                            WHERE t2.IDPK = t1.IDPK   
                            ORDER BY ITEMID, QTY  
                            FOR XML PATH('')  
                        ),1,1,''  
                      )
    FROM @Rows t1  
    GROUP BY IDPK 
),
cteFilter AS(
  SELECT h1.IDPK AS IDPK1, h2.IDPK AS IDPK2
    FROM cteHeaderRows h1
    JOIN cteHeaderRows h2 ON h1.IDPK != h2.IDPK AND h1.ItemIDs = h2.ItemIDs AND h2.Qtys = h1.Qtys
)
SELECT DISTINCT h.IDPK, h.Description, r.ItemID, r.Qty
  FROM @Headers h
  JOIN cteFilter f ON f.IDPK1 = h.IDPK
  JOIN @Rows r ON r.IDPK = f.IDPK1
ORDER BY 1,3,4
t98cgbkg

t98cgbkg2#

假设没有重复项:

with r as (
      select r.*, count(*) over (partition by idpk_header) as num_items
      from rows r
     )
select r1.idpk_header, r2.idpk_header
from r r1 join
     r r2
     on r1.item_id = r1.item_id and r2.qty = r1.qty and r2.num_items = r1.num_items
group by r1.idpk_header, r2.idpk_header, r1.num_items
having count(*) = r1.num_items;

基本上,这会对项目进行自连接,因此您只能获得匹配项。这个 on 验证两者的项数是否相同。以及 having 保证所有匹配。
注意:此版本将头的每个匹配项返回给自身。那是一张不错的支票。你当然可以把它过滤掉 on 或者 where 条款。
如果你有重复的项目,你可以简单地替换 r 使用:

select idpk_header, item_id, sum(qty) as qty,
       count(*) over (partition by idpk_header) as num_items
from rows r
group by idpk_header, item_id;

相关问题