web-dev-qa-db-ja.com

Postgresのネストされたhstore選択クエリ

アイテムのhstore列を含むカートテーブルがあります。この列のエントリの例は次のとおりです。

carts.items row#1 = {
                     "1614" => {:quantity=>"100", :price_cents=>1655},
                     "1938" => {:quantity=>"50", :price_cents=>1955},
                     "1983" => {:quantity=>"100", :price_cents=>2255},
                     "1322" => {:quantity=>"10", :price_cents=>4455},
                     "1691" => {:quantity=>"25", :price_cents=>1055},
                     "1734" => {:quantity=>"20", :price_cents=>1255}
                    }

carts.items row#2 = {"1614"=>{:quantity=>"50", :price_cents=>1655}}

したがって、私のカートテーブルは次のようになります。

    id   | items  
---------+-------
    1    |   {"1614"=>{:quantity=>"100", :price_cents=>1655}, "1938" => {:quantity=>"50", :price_cents=>1955},"1983"=>{:quantity=>"100", :price_cents=>2255},"1322"=>{:quantity=>"10", :price_cents=>4455},"1691"=>{:quantity=>"25", :price_cents=>1055},"1734"=>{:quantity=>"20", :price_cents=>1255}}
    2    |   {"1614"=>{:quantity=>"50", :price_cents=>1655}}

ハッシュに重複したID(1614)が1つあることに気づくでしょうが、その数量は異なります。

アイテムIDカウントと合計数量を含むテーブルを返すクエリを作成したいと思います。次のようになります。

 item_id | count | total 
---------+-------+------
   1614  |   2   |  150
   1938  |   1   |  50
   1983  |   1   |  50
   1322  |   1   |  100

これが私が使っているクエリです:

SELECT  
skeys(carts.items) as item_ids,
COUNT(*) AS count,
svals(carts.items) as items
FROM carts
GROUP BY
skeys(carts.items),
svals(carts.items)

それは返します:

 item_id | count | total 
---------+-------+------
   1614  |   1   |  {:quantity=>100}
   1614  |   1   |  {:quantity=>50}
   1938  |   1   |  {:quantity=>50}
   1983  |   1   |  {:quantity=>50}
   1322  |   1   |  {:quantity=>100}

私も試した:

SELECT key, count(*) FROM
  (SELECT (each(items)).key FROM carts) AS stat
GROUP BY key
ORDER BY count DESC, key;

これは私にこれを与えます:

item_id | count 
---------+-------
   1614  |   2    
   1938  |   1   
   1983  |   1   
   1322  |   1   
2
mpiccolo

元の質問(hstore値内の重複)

あなたの問題の根本的な原因はこれで説明されていると思います マニュアルからの引用

Hstoreの各キーはuniqueです。重複するキーを使用してhstoreを宣言すると、1つだけがhstoreに格納され、どちらが保持されるかは保証されません。

大胆な強調鉱山。

単一のhstore値に同じキーが2つある可能性があると思い込んでいます。

2countも再現できません。キー1に対してcount of 1614を取得しました。列名としてcountを使用しないことから始めます。 予約語 です(ただし、Postgresでは許可されています)。

私は得ます(Postgres 9.1.9でテスト済み):

WITH carts AS (
   SELECT '"1614"=>{:quantity=>"100"}, "1938"=>{:quantity=>"50"}, "1614"=>{:quantity=>"50"}, "1983"=>{:quantity=>"100"}, "1322"=>{:quantity=>"10"}, "1691"=>{:quantity=>"25"}, "1614"=>{:quantity=>"77"}, "1734"=>{:quantity=>"20"}'::hstore items
    )
SELECT key, count(*) AS ct FROM
  (SELECT (each(items)).key FROM carts) AS stat
GROUP BY key
ORDER BY ct DESC, key;

結果:

 key  | ct
------+----
 1322 |  1
 1614 |  1
 1691 |  1
 1734 |  1
 1938 |  1
 1983 |  1

更新された質問(複数行にわたる複製)

値を集計するには、サブクエリ(またはCTE)が必要です。

簡略化されたテストケース:

CREATE TEMP TABLE carts(c_id serial, items hstore); 
INSERT INTO carts(items) VALUES
   ('"1614"=>"100", "1938"=>"50", "1983"=>"100", "1322"=>"10", "1691"=>"25", "1734"=>"20"')
  ,('"1614"=>"50"');

クエリ:

SELECT item_ids, count(*) AS ct, sum(items) AS sum_items
FROM (
   SELECT (each(items)).key AS item_ids
         ,(each(items)).value::int AS items  -- assuming values can be cast to int
   FROM   carts
   ) sub
GROUP  BY 1           -- positional parameter is just a notational convenience
ORDER  BY 2 DESC;

結果:

 item_ids | ct | sum_items
----------+----+-----------
 1614     |  2 |       150
 1734     |  1 |        20
 1691     |  1 |        25
 1983     |  1 |       100
 1938     |  1 |        50
 1322     |  1 |        10
2