在Ms Access / SQL Server中确定归纳定义的数据

时间:2011-09-09 08:22:21

标签: c# sql-server ms-access

我需要使用c#.net(3.5)从MsAccess / SQL Server(我面临类似问题的两个独立项目)中检索数据,最好是快速的,并且代码可以理解/可维护/简单。

我有以下表格列。对于每个,以粗体列的列是键(也是索引)。

  • SKU信息(~1000 000条记录): PNO,描述,提前期,价格等等
  • 使用信息(约200 000条记录): OrderNO ,PNO,描述,日期,数量,计量单位等等
  • InterchangeAbility(约100 000条记录): PNO,描述(PNO1,description1,etcetera)

最后一个表格表明(PNO1,description1)是(PNO,描述)的后继SKU。注意,(PNO1,description1)也可以具有后继者。

我需要检索并存储在内存中:

  1. 所有用法
  2. 有用的任何部件的SKU信息(约20000个部件)
  3. 所有相关互换性记录,其中说明了有用的部件或者部件的后续变体,其中有使用等等。
  4. 任何相关首选部件(约2000件)的SKU信息
  5. 是否有人为此问题提供了良好的可维护解决方案?

    最有希望的方法似乎是在数据库方面确定与SKU相关。问题是,相关性是归纳定义的。怎么做?

3 个答案:

答案 0 :(得分:1)

威廉,这听起来像是你的祖先树。

举一个例子,你有A部分由B部分继承,部分B由部分C或D继承。然后说,D成功了部分E.这给你:

Part  | All Successors                   A
----------------------                  / 
A     | B, C, D, E                     B
B     | C, D, E                       / \
C     | -                            C   D
D     | E                                 \
E     | -                                  E

因此,您需要在数据库中跟踪的是另一部分成功的 root 部分,而不仅仅是它的直接祖先。

如果您能够更改架构,我会在InterchangeAbility表中添加另外两个字段,跟踪RootPNO,RootDescription(索引在一起)。每当一个部分成功完成另一个部分时,你也需要记录所有祖先的继承。

然后,您可以从使用表中直接加入InterchangeAbility中的 Root 字段,以获取部件的所有可能的成功。

答案 1 :(得分:0)

您可以查看缓存数据。

例如,memcached(http://sourceforge.net/projects/memcacheddotnet/)。

基本上使用常设查询与您的基础数据同步,然后内存中始终可以使用该数据。

答案 2 :(得分:0)

试图弄清楚如何使用CTE解决找到相关可互换性的问题。很快就失控了。你或许可以从中得到一些东西。假设我的想法并非完全错误,它应该不会低效,尽管它的大小。

CTE内的每个查询基本上都是您可以从CTE访问的临时视图。 Preferred,Roots和HasUsage位不依赖于任何其他CTE表,因此如果需要,它们实际上甚至可以是视图。

;WITH Preferred AS (
   -- Find leaves (Any PNO which replaces a PNO but is never replaced.)
  SELECT PNO1 FROM InterchangeAbility l 
  LEFT JOIN InterchangeAbility r ON l.PNO1 = r.PNO
  WHERE r.PNO IS NULL  
)
, Roots AS (
  -- Find roots (Any PNO which gets replaced, but never replaces anything.)
  SELECT PNO FROM InterchangeAbility l
  LEFT JOIN InterchangeAbility R ON l.PNO = r.PNO1
  WHERE r.PNO1 IS NULL
)
, HasUsage AS (
   -- Count number of records in usage for each PNO in usage (including 0)
   -- Ideally this step wouldn't be necessary, but a LEFT JOIN isn't allowed in 
   -- The recursive part of a CTE.  There may be a more efficient way around this step.
  SELECT SkuInfo.PNO, COUNT(Usage.PNO) AS num_records
  FROM SkuInfo
  LEFT JOIN Usage ON SkuInfo.PNO = SkuInfo.Usage
  GROUP BY SkuInfo.PNO
)
, TreeHasUsage AS (
  -- Traverse from root to leaf, used leaves will have nonzero usage
  -- This is a recursive query, The usage of each root will be the base case.
  SELECT p.PNO AS root, p.PNO AS curr, hu.num_records 
  FROM Roots p
  INNER JOIN HasUsage hu ON p.PNO = hu.PNO 
  UNION ALL
  -- This is the recursive part of the query, it finds the PNO which replaces
  -- the root element (and so on) and does a running total of the usage associated
  -- with this tree branch.  By the time we get to a leaf any relevant preferred PNOs
  -- will have a nonzero num_records.
  SELECT tu.root, hu.PNO, tu.num_records + hu.num_records 
  FROM TreeHasUsage tu 
  INNER JOIN InterchangeAbility i ON tu.curr = i.PNO1 
  INNER JOIN HasUsage hu ON i.PNO = hu.PNO  
)
, RelevantRoots AS (
  -- Important tree nodes are the ones which have a non zero 
  -- num_records on one or more leaves. Select the roots of those trees.
  SELECT DISTINCT hu.root FROM Preferred p 
  INNER JOIN TreeHasUsage hu WHERE p.PNO1 = hu.curr
  WHERE hu.num_records > 0 
)
-- Select every record in InterchangeAbility which belongs to one of the 
-- just determined relevant roots.
SELECT * FROM InterchangeAbility i 
INNER JOIN RelevantRoots rr ON i.PNO = rr.root