一组数字中存在的值(SQL)

时间:2016-02-26 18:18:29

标签: sql postgresql pivot crosstab

我想知道我在给定日期和特定商店(我们有)给定范围尺寸(比如3:X,Y,Z)的模型(比如说T恤)有多少说3:A,B,C)库存。

其中:

X = between 40 and 50
Y = between 30 and 60
Z = between 20 and 70

最终输出看起来像这样(但有很多结果):

 Date  | Store | Model | Availability X | Availability Y | Availability Z
 02/26 | A     | shirt | Yes            | Yes            | No
 02/26 | B     | shirt | Yes            | No             | No
 02/26 | C     | shirt | Yes            | Yes            | Yes

可用性意味着我必须拥有给定尺寸范围之间的所有尺寸。

我仍然想找到一种方法来做到这一点。我现在的表格就是这样设计的(一些说明性信息):

表“设置”

     id | name     | initial_value | final_value
     1  | X        | 40            | 50
     2  | Y        | 30            | 60
     3  | Z        | 20            | 70

表“项目”

     id | date     | store | model     | size    | in_stock
     1  | 02/26    | A     | shirt     | 40      | 1
     2  | 02/26    | A     | shirt     | 50      | 2
     3  | 02/26    | A     | shirt     | 30      | 0
     4  | 02/26    | B     | shirt     | 30      | 1

我感谢任何帮助!感谢。

3 个答案:

答案 0 :(得分:1)

这是SQL Server的输出,我不知道postgresql。

- 创建SETS

create table dbo.test_sets
(
  id int not null,
  name varchar(255),
  initial_value int not null default (0),
  final_value int not null default(0)
)
go

insert into dbo.test_sets( id, name, initial_value, final_value)
values (1, 'X', 40, 50)

insert into dbo.test_sets( id, name, initial_value, final_value)
values (2, 'Y', 30, 60)

insert into dbo.test_sets( id, name, initial_value, final_value)
values (3, 'Z', 20, 70)
go

- 创建ITEMS

create table dbo.test_items
(
  id int not null,
  [date] date,
  store varchar(255) not null,
  model varchar(255) not null,
  size int not null default (0),
  in_stock int not null default(0)
)
go

insert into dbo.test_items( id, [date], store, model, size, in_stock)
values (1, '02/26/2016', 'A', 'shirt', 40, 1)

insert into dbo.test_items( id, [date], store, model, size, in_stock)
values (2, '02/26/2016', 'A', 'shirt', 50, 2)

insert into dbo.test_items( id, [date], store, model, size, in_stock)
values (3, '02/26/2016', 'A', 'shirt', 30, 0)

insert into dbo.test_items( id, [date], store, model, size, in_stock)
values (4, '02/26/2016', 'B', 'shirt', 30, 1)

insert into dbo.test_items( id, [date], store, model, size, in_stock)
values (5, '02/26/2016', 'C', 'shirt', 80, 1)
go

- 创建NUMBERS LOOKUP

create table dbo.test_numbers
(
  id int not null
)
go

declare @first as int
declare @step as int
declare @last as int
select @first = 1, @step = 1, @last = 100

BEGIN TRANSACTION
    WHILE(@first <= @last) 
    BEGIN 
        INSERT INTO dbo.test_numbers VALUES(@first) SET @first += @step 
    END 
COMMIT TRANSACTION
go

- 查询以提供所需的输出

;with unique_store_models as
(
    select distinct store, model from dbo.test_items
),
set_sizes as
(
    select ts.id, ts.name as size_group, tn.id as size 
    from 
        dbo.test_sets ts 
        inner join dbo.test_numbers tn on 
            tn.id between ts.initial_Value and ts.final_value
),
items_by_sizes_flat as
(
    select 
        ti.[date],
        usm.store,
        usm.model,
        ss.size_group,
        ss.size,
        ti.in_stock
    from 
      unique_store_models usm
      left outer join dbo.test_items ti on 
        ti.store = usm.store 
        and ti.model = usm.model
      left outer join set_sizes ss on 
        ss.size = ti.size
),
items_by_sizes_pivoted as
(
    select
        *
    from
    (
        select
            [date],
            store,
            model,
            size_group,
            --size,
            in_stock
        from 
            items_by_sizes_flat
    ) as p
    PIVOT
    (
        count(in_stock) for size_group in ([X], [Y], [Z])
    ) as pv
)
select 
    [date], 
    store, 
    model, 
    case 
        when [X] > 0 then 'Yes' else 'No' 
    end as [Availability X],
    case 
        when [Y] > 0 then 'Yes' else 'No' 
    end as [Availability Y], 
    case 
        when [Z] > 0 then 'Yes' else 'No' 
    end as [Availability Z] 
from 
    items_by_sizes_pivoted

以下是上述输入的输出:

enter image description here

答案 1 :(得分:0)

也许你可以尝试这样的事情:

SELECT      date,
            store,
            model,
            SUM(
                CASE
                    WHEN size BETWEEN (SELECT initial_value FROM Table "sets" WHERE id = 1) AND (SELECT final_value FROM Table "sets" WHERE id = 1) 
                        THEN in_stock
                    ELSE 0
                END
            )       as "Availability X",
            SUM(
                CASE
                    WHEN size BETWEEN (SELECT initial_value FROM Table "sets" WHERE id = 2) AND (SELECT final_value FROM Table "sets" WHERE id = 2) 
                        THEN in_stock
                    ELSE 0
                END
            )       as "Availability Y",
                CASE
                    WHEN size BETWEEN (SELECT initial_value FROM Table "sets" WHERE id = 3) AND (SELECT final_value FROM Table "sets" WHERE id = 3) 
                        THEN in_stock
                    ELSE 0
                END
            )       as "Availability Z"


FROM        Table "items"

WHERE       date > '02/26/2016'
            AND
            date < '02/26/2016'
            AND
            Model = 'shirt'

GROUP BY    date, store, model

我认为这会为您提供您之后的信息,但如果您想要完全按照您的要求输出,那么您可以围绕每个可用性案例声明包装另一个案例陈述,或使用如下的CTE: / p>

WITH
data AS
(
SELECT      date,
            store,
            model,
            SUM(
                CASE
                    WHEN size BETWEEN (SELECT initial_value FROM Table "sets" WHERE id = 1) AND (SELECT final_value FROM Table "sets" WHERE id = 1) 
                        THEN in_stock
                    ELSE 0
                END
            )       as availability_x,
            SUM(
                CASE
                    WHEN size BETWEEN (SELECT initial_value FROM Table "sets" WHERE id = 2) AND (SELECT final_value FROM Table "sets" WHERE id = 2) 
                        THEN in_stock
                    ELSE 0
                END
            )       as availability_y,
            SUM(
                CASE
                    WHEN size BETWEEN (SELECT initial_value FROM Table "sets" WHERE id = 3) AND (SELECT final_value FROM Table "sets" WHERE id = 3) 
                        THEN in_stock
                    ELSE 0
                END
            )       as availability_z


FROM        Table "items"

WHERE       date > '02/26/2016'
            AND
            date < '02/26/2016'
            AND
            Model = 'shirt'

GROUP BY    date, store, model
)

SELECT      date, store, model,
            CASE
                WHEN availability_x > 0 THEN "Yes"
                ELSE "No"
            END as "Availability X",
            CASE
                WHEN availability_y > 0 THEN "Yes"
                ELSE "No"
            END as "Availability Y",
            CASE
                WHEN availability_z > 0 THEN "Yes"
                ELSE "No"
            END as "Availability Z"

FROM        data

答案 2 :(得分:0)

crosstab()用例的典型示例。

示例数据:

-- DDL and data
CREATE TABLE items(
  id SERIAL PRIMARY KEY,
  "Date" DATE,
  store TEXT,
  model TEXT,
  size INTEGER,
  in_stock INTEGER
);
INSERT INTO items VALUES
  (1, '02/26/2016':: DATE, 'A', 'shirt', 40, 1),
  (2, '02/26/2016':: DATE, 'A', 'shirt', 50, 2),
  (3, '02/26/2016':: DATE, 'A', 'shirt', 30, 0),
  (4, '02/26/2016':: DATE, 'B', 'shirt', 30, 1);
CREATE TABLE sets(
  id SERIAL PRIMARY KEY,
  name TEXT,
  initial_value INTEGER,
  final_value INTEGER
);
INSERT INTO sets VALUES
  (1, 'X', 40, 50),
  (2, 'Y', 30, 60),
  (3, 'Z', 20, 70);

为了选择我使用int4range(start,end,inclusion)函数来配置大小范围include.Query本身:

SELECT * FROM crosstab(
  'SELECT i.store,i."Date",i.model,s.name,
     bool_or(CASE WHEN size_range @> i.size
               THEN TRUE
               ELSE FALSE
             END)
   FROM items i,sets s,int4range(s.initial_value, s.final_value, ''[)'') AS size_range
   WHERE i.in_stock > 0
   GROUP BY 1,2,3,4
   ORDER BY 1,2',
   'SELECT DISTINCT(name) FROM sets ORDER BY 1')
AS output(store TEXT,"Date" DATE,model TEXT,"Availability X" BOOLEAN,"Availability Y" BOOLEAN,"Availability Z" BOOLEAN);

结果:

 store |    Date    | model | Availability X | Availability Y | Availability Z 
-------+------------+-------+----------------+----------------+----------------
 A     | 2016-02-26 | shirt | t              | t              | t
 B     | 2016-02-26 | shirt | f              | t              | t
(2 rows)