1

次のテーブルがあるとします。

CREATE TABLE #temp(AnimalId varchar(5), BodyPartId varchar(5), Value decimal)
INSERT INTO #temp
SELECT 'A', 'X', 50 union all
SELECT 'A', 'Y', 75 union all
SELECT 'A', 'B', 100 union all
SELECT 'B', 'K', 60 union all
SELECT 'B', 'J', 53

動物は、特定の値を持つ体の部分で構成されています。彼らの体の部分は他の動物である可能性もあります。

他の動物の体の部分を他の動物の体の部分の値に置き換えることができる必要があります。

SQLでこれを行うことは可能ですか?

上記の例を使用して計算するには、体のどの部分が動物であるかを調べます (B)。次に、これらの動物について、体の各部分が占める割合を計算します。

K divided by total of B: 60/113 = 0.53
J divided by total of B: 53/113 = 0.47

次に、これらの値に A の B の合計を掛けます。

Ks percentage times 100: 0.53 * 100 = 53
Js percentage times 100: 0.47 * 100 = 47

したがって、動物 A の最終的な構成は次のようになります。

X 50
Y 75
K 53
J 47

動物に対する各体の部分の割合を見つけるのに苦労しています。動物は、体の部分だけで構成されている他の動物でしか構成できないと想定しているため、再帰的な解決策は必要ありません (ただし、それを見るのは良いことです)。

4

1 に答える 1

3

うまくいくと思われる解決策をまとめましたが、より複雑なシナリオでテストするか、サブサブアニマルや複数のサブである動物など、どのタイプのシナリオが関係するかを知ることをお勧めします親動物、または体の一部の複製など。

最初に、親動物の亜動物である動物の一部である体の部分のパーセンテージと合計を計算し、新しい合計で表を更新します。また、正しい新しい親動物と一致するように親動物を更新します。

-- update body parts of sub-animals to new value and parent animal
-- also set parent animal bodypartid to itself so it can be identified
with animalbodyparts as (
  select * from animals
  where bodypartid in (select animalid from animals)
), totals as (
  select a.animalid, sum(a.value) as subtotal
  from animals a
  group by a.animalid
), newtotals as (
  select ab.animalid as parentanimalid, t.animalid,
    p.bodypartid, p.value / t.subtotal as percentage,
    ab.value as newtotal, cast(p.value / t.subtotal * ab.value as integer) as newvalue
  from animalbodyparts ab
  join totals t on ab.bodypartid = t.animalid
  join animals p on t.animalid = p.animalid
)
update a
set
  a.animalid = 
    case
      when t.parentanimalid is null then a.animalid
      else t.parentanimalid
    end,
  a.bodypartid =
    case
      when t.animalid = a.bodypartid then t.parentanimalid
      else a.bodypartid
    end,
  a.value =
    case
      when t.newvalue is null then a.value
      else t.newvalue
    end
from animals a
left join newtotals t on a.bodypartid = t.bodypartid
  or t.animalid = a.bodypartid;

また、bodypartid が体の一部として子動物への参照であった場合、bodypartid を親動物と同じになるように更新します。これは、サブパーツの animalid を更新すると、以前は動物を参照していたボディ パーツを参照する方法が他にないためです。同じ値に更新して、bodypartid と animalid の値が一致するようになったので、どれを削除する必要があるかがわかります。

--cleanup by removing the body parts that were sub-animals
delete from animals where animalid = bodypartid

デモ: http://www.sqlfiddle.com/#!3/6a5a0/39

注:新しい値を計算する前に最初にパーセンテージを丸めているのに対し、合計計算後に丸めているため、最終結果は46forになります。J必要に応じて変更するのは非常に簡単です。いずれの方法でも、新しい値が元の古い合計の合計になるという保証はないことに注意してください (つまり、47 + 53 = 100)。最初に丸めたとしても、元の合計とはわずかに異なる合計になるという - まれな - 病理学的シナリオ (おそらくサブ動物の 3 つ以上の体の部分が関与する) があります。

于 2012-08-23T13:53:43.023 に答える