1

私のデータ ウェアハウスでは、各レコードが 1 つまたは複数のタグを持つことができるディメンションを取得しました。異なるタグでディメンションをモデル化する簡単な方法はありますか?

私の最初のアイデアは、カンマ区切りのリストを保存し、MySQL:s FIND_IN_SET() 関数を使用してタグの存在をテストすることでした。これにより、データをスライスできます。

しかし、タグでグループ化できるようにしたい場合、スキームをどのようにモデル化すればよいでしょうか?

例:

2 つの製品: 製品 A と製品 B。A は「foo」、「bar」でタグ付けされています。B は 「bar」「baz」等のタグがつけられた作品です。

クエリ: 商品タグごとにグループ化された売上高。タグ「bar」のグループには、製品 A と B の両方の売上が含まれている必要があります。

foo -> sales for A
bar -> sales for B and A
baz -> sales for C
4

3 に答える 3

1

たとえば、タグによって複製されたデータを保存できます。

売上が a=10 foo + bar で b=20 bar + baz の場合、次のように保存できます。

    sales_by_tag_facts
    id, tag, sale_id, amount, is_primary_record
    1   foo  A        10     true
    2   bar  A        10     false
    3   bar  B        20     true
    4   baz  B        20     false

select sum(amount) from sales_by_tag_facts group by tag; // by tag
select sum(amount) from sales_by_tag_facts where is_primary_record=true; // without tag.
于 2011-04-13T19:56:57.423 に答える
0

重労働を報告から取引予約に移してみませんか

次の名前の新しいテーブルを追加できます。

TagTotalは、タグごとの合計金額を格納し、BEFORE(AFTER)_UPDATE_EACHトリガーを介してトランザクションごとに更新します。

追加のフィールド/テーブル

productテーブルに2つの追加フィールドがある場合:

product.amount    decimal(10,2) running total of sales to date
product.last_sale date          date of the last sale

そして、タグ合計テーブルは次のようになります。

tag.id primary autoinc    
tag.tagstr varchar(25)     
tag.amount decimal(10,2)
tag.date_from date   #dates to keep the running totals per month/week/day.
tag.date_to   date

擬似コード

CREATE TRIGGER ai_sales_each AFTER INSERT ON sales FOR EACH ROW
BEGIN
  UPDATE product SET product.amount = product.amount + new.amount,
    product.last_sale = sale.date
END

CREATE TRIGGER au_product_each AFTER UPDATE ON product FOR EACH ROW
BEGIN
  DECLARE AllTags VARCHAR(255);
  DECLARE ThisTag VARCHAR(25);

  IF old.tags <> new.tags THEN BEGIN
    reorganize the running totals in the tagtotal table.
  END; END IF;

  SET AllTags = new.tags;
  WHILE AllTags has more tags BEGIN
    SET ThisTag = NextTag(AllTags);
    UPDATE TagTotals SET amount = amount + new.amount
      WHERE TagTotals.tagstr = ThisTag 
      AND new.last_date BETWEEN TagTotals.date_from AND TagTotals.date_to;
  END; END WHILE; 

これで、タグごとの売上合計が必要な場合は、tagtotalsテーブルから選択できます。
すぐに結果が得られます。

于 2011-04-14T08:03:40.360 に答える
-1

私はそれに対してお勧めします、それは正規化規則に反します。私は1NFを台無しにし続けるか、正規化タグ の下の投稿を読んで
ください。

テーブルの再設計提案

このようにタグとタグリンクテーブルを作成すると。

table tag
  id autoincrement integer primary index 
  tag_str varchar(20) index unique not null

table taglink
  id autoincrement integer primary index #gotta have an ID in my book.
  tag_id integer not null
  product_id integer not null

このような販売テーブルがあります。

table product
  id autoincement integer primary index
  desc varchar(255)
  barcode, price, whatever ...

タグごとに製品を検索する select ステートメント

次のようにタグに一致する記事を検索できます。

select * from product
inner join taglink on (product.id = taglink.product_id)
inner join tag on (taglink.tag_id = tag.id)
where tag.tag_str in ('foo','bar','baz');

製品ごとにタグを一覧表示する select ステートメント

select tag_str from tag
inner join taglink on (taglink.tag_id = tag.id)
inner join product on (taglink.product_id = product.id)
where product.barcode = '4548215' or product.desc like 'OMG Po%'

新しいタグの追加

新しいタグを追加するには、

insert into tag (id, tag_str) values (
  null /*remember autoincrement*/
  ,'Mytag');

タグのリンク

タグを商品にリンクするには

set @product_id = 10;
set @tag_id = 1;
...or...
select @product_id:= product.id from product where product.barcode = '1254851';
...
insert into taglink (id, product_id, tag_id) values (
  null /*autoinc id*/
  ,@product_id
  ,@tag_id );

FIND_IN_SET無制限の数のタグを製品にリンクでき、コストのかかるステートメントでクエリを遅くすることはありません.
また、タグの重複を防ぎます。
また、データベースはより高速で小さくなります。

于 2011-04-13T20:20:59.053 に答える