SQL - 计算不同价格diapasons

时间:2018-03-24 20:28:11

标签: sql

我有一个关于SQL的问题,老实说我在尝试之前尝试搜索方法。我将在下面给出一个抽象(但精确)的描述,并将非常感谢您的解决方案示例(SQL查询)。

我有什么:

  1. 表A包含项目的类别ID ,每个项目的价格(以美元为单位)。 类别ID 具有 int 类型的值,价格字符串,看起来像" USD 200000000&#34 ; (实际值乘以10 ^ 7)。表格还有列,其中 int 类型的值。

  2. 表B与类别ID 名称的关系。

  3. 我需要什么:

    获取价格diapasons(如0-100 | 100-200 | ...)作为列名称的表格,并计算每个类别ID (作为行名称)的项目数量价格diapasons。所有结果必须通过种类参数(来自表A)进行过滤,其值为 3

    我遇到的问题(以及导致询问SQL查询示例的问题):

    1. 价格字符串值中剪切" USD ,除以10 ^ 7并转换为浮动。
    2. 收集价格值(0-100 | 100-200 | ...)的结果,给定时间间隔内的给定步骤(最开始时价格被视为未知)。示例:在0-500区间内执行 100 ,对于值> 500,步骤 200
    3. 价格值的对数放入结果表的列名中。
    4. 对于每个diapason,计算每个类别中的项目数量(category_id)。不考虑滞后的左边界限(例如,在1000-1200 diapason,不考虑价格1000的项目)。
    5. 使用B表,显示名称而不是类别ID
    6. 感谢回应,无知将被理解。

2 个答案:

答案 0 :(得分:1)

如果您只需要类别ID,则不需要B。您正在寻找的是条件聚合,例如:

select category_id,
       sum(case when cast(substring(price, 4, 100) as int)/10000000 < 100 then 1 else 0 end) as price_000_100
       sum(case when cast(substring(price, 4, 100) as int)/10000000 >= 100 and cast(substring(price, 4, 100) as int)/10000000 < 200
                then 1 else 0
           end) as price_100_200,
       . . .                 
from a
group by category_id

答案 1 :(得分:1)

没有标准的方法来做你所描述的。

那是因为做(3)你需要一个虚拟对象交叉表,而这不是ANSI SQL。每个DBMS都有自己的实现。另外,数据透视表中的动态列是一个额外的复杂功能。

例如,Postgres称之为&#34;交叉号&#34;并要求安装tablefunc模块。见SO questiondocumentation。与使用PIVOT command

的SQL Server进行比较

您可以使用合理标准的SQL来接近。

以下是基于SQLite的示例。一点点的转换将为其他系统提供解决方案,例如在postgre中SUBSTR substring(string [from int] [for int])

假设格式为数据表:

data table

和类别名称表:

category name table

然后以下代码将产生:

output as list

WITH dataCTE AS
    (SELECT product_id AS 'ID', CAST(SUBSTR(price, 5) AS INT)/1000000 AS 'USD',
    CASE WHEN (CAST(SUBSTR(price, 5) AS INT)/1000000) <= 500 THEN
        100 ELSE 200
        END AS 'Interval'
    FROM data
    WHERE kind = 3),
groupCTE AS
    (SELECT dataCTE.ID AS 'ID', dataCTE.USD AS 'USD', dataCTE.Interval AS 'Interval',
    CASE WHEN dataCTE.Interval = 100 THEN 
        CAST(dataCTE.USD AS INT)/100
    ELSE
        (CAST(dataCTE.USD-500 AS INT)/200)+5
    END AS 'GroupID'
    FROM dataCTE),
cleanCTE AS
    (SELECT *, CASE WHEN groupCTE.Interval = 100 THEN
        CAST(groupCTE.GroupID *100 AS VARCHAR) 
        || '-' || 
        CAST((groupCTE.GroupID *100)+99 AS VARCHAR)
    ELSE
        CAST(((groupCTE.GroupID-5)*200)+500 AS VARCHAR) 
        || '-' || 
        CAST(((groupCTE.GroupID-5)*200)+500+199 AS VARCHAR) 
    END AS 'diapason'
    FROM groupCTE
    INNER JOIN cat_name AS cn ON groupCTE.ID = cn.cat_id)
SELECT *
FROM cleanCTE;

如果您将最后SELECT修改为:

SELECT name, diapason, COUNT(diapason)
FROM cleanCTE
GROUP BY name, diapason;

然后你得到一个分组输出:

output as group

在没有指定确切系统的情况下,这将尽可能接近;即使这样,你也会遇到动态创建列名的问题。