提取所有行的sql server查询

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

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

  1. Header: IDPK | Description
  2. Row: IDPK | IDPK_Header | Item_ID | Qty

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

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

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

pqwbnv8z

pqwbnv8z1#

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

  1. DECLARE @Headers TABLE(
  2. IDPK INT,
  3. Description NVARCHAR(100)
  4. )
  5. DECLARE @Rows TABLE(
  6. IDPK INT,
  7. ITEMID NVARCHAR(1),
  8. Qty INT
  9. )
  10. INSERT INTO @Headers VALUES
  11. (1, 'Test1'),
  12. (2, 'Test2'),
  13. (3, 'Test3'),
  14. (4, 'Test4'),
  15. (5, 'Test5')
  16. INSERT INTO @Rows VALUES
  17. (1, 'A', 10),
  18. (1, 'B', 20),
  19. (2, 'A', 10),
  20. (2, 'B', 20),
  21. (3, 'A', 5 ),
  22. (3, 'B', 20),
  23. (4, 'C', 10),
  24. (5, 'A', 10),
  25. (5, 'C', 20)
  26. ;
  27. WITH cteHeaderRows AS(
  28. SELECT IDPK
  29. ,ItemIDs=STUFF(
  30. (
  31. SELECT ',' + CAST(ITEMID AS VARCHAR(MAX))
  32. FROM @Rows t2
  33. WHERE t2.IDPK = t1.IDPK
  34. ORDER BY ITEMID, QTY
  35. FOR XML PATH('')
  36. ),1,1,''
  37. )
  38. ,Qtys=STUFF(
  39. (
  40. SELECT ',' + CAST(Qty AS VARCHAR(MAX))
  41. FROM @Rows t2
  42. WHERE t2.IDPK = t1.IDPK
  43. ORDER BY ITEMID, QTY
  44. FOR XML PATH('')
  45. ),1,1,''
  46. )
  47. FROM @Rows t1
  48. GROUP BY IDPK
  49. ),
  50. cteFilter AS(
  51. SELECT h1.IDPK AS IDPK1, h2.IDPK AS IDPK2
  52. FROM cteHeaderRows h1
  53. JOIN cteHeaderRows h2 ON h1.IDPK != h2.IDPK AND h1.ItemIDs = h2.ItemIDs AND h2.Qtys = h1.Qtys
  54. )
  55. SELECT DISTINCT h.IDPK, h.Description, r.ItemID, r.Qty
  56. FROM @Headers h
  57. JOIN cteFilter f ON f.IDPK1 = h.IDPK
  58. JOIN @Rows r ON r.IDPK = f.IDPK1
  59. ORDER BY 1,3,4
展开查看全部
t98cgbkg

t98cgbkg2#

假设没有重复项:

  1. with r as (
  2. select r.*, count(*) over (partition by idpk_header) as num_items
  3. from rows r
  4. )
  5. select r1.idpk_header, r2.idpk_header
  6. from r r1 join
  7. r r2
  8. on r1.item_id = r1.item_id and r2.qty = r1.qty and r2.num_items = r1.num_items
  9. group by r1.idpk_header, r2.idpk_header, r1.num_items
  10. having count(*) = r1.num_items;

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

  1. select idpk_header, item_id, sum(qty) as qty,
  2. count(*) over (partition by idpk_header) as num_items
  3. from rows r
  4. group by idpk_header, item_id;
展开查看全部

相关问题