多聚合、多过滤器、单表 SQL

发布于 2024-12-23 08:25:18 字数 1893 浏览 1 评论 0原文

以下模拟表包含订单详细信息,其中 cust_nbr 代表订单号。我正在尝试查找如果订单包含 item_nbr 90000,我需要知道 90000 的价格是否大于其他商品加税的总和。我在这个表中有数十万条记录。我正在使用 Teradata。

CREATE TABLE Line_Item_Details_Tbl (
    cust_nbr INT,
    trn_dt DATE,
    str_typ VARCHAR(6),
    trn_nbr INT,
    item_nbr INT,
    price DECIMAL(6,2),
    tax DECIMAL(6,2)
);

示例数据:

INSERT INTO Line_Item_Details_Tbl VALUES 
  (5551, '12/22/2011',  'store', 215, 12345, 10.00, 1.25);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (5551, '12/22/2011',  'store', 215, 65715,  6.25, 0.75);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (5551, '12/22/2011',  'store', 215, 90000, 40.00, 0);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (6875, '12/10/2011', 'online', 856, 72345,  8.50, 1.00);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (6875, '12/10/2011', 'online', 856, 65715,  6.25, 0.75);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (3500, '12/12/2011',  'store', 402, 54123, 45.00, 4.00);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (3500, '12/12/2011',  'store', 402, 90000, 20.00, 0);
INSERT INTO Line_Item_Details_Tbl VALUES 

查询应执行以下操作:

Select cust_nbr, trn_dt, trn_nbr, sum(price + tax) as purchase
  For a cust_nbr with str_typ  = 'store' AND contains an item_nbr = 90000,
  aggregate price + tax for all items related to cust_nbr except item_nbr 90000

因此,初步结果应为:

cust_nbr  :   trn_dt   : trn_nbr : purchase
5551        12/22/2011   215       $18.25           
3500        12/12/2011   402       $49.00           

然后,对于初步结果中的每条记录,我需要从 purchase< 中减去 item_nbr 90000 的价格/code> 仅当购买量小于时才返回结果 item_nbr 90000 的价格为 net_cb

所以,我的最终结果应该是:

cust_nbr  trn_dt       trn_nbr  net_cb
  5551    12/22/2011   215      ($21.75)            

The following simulated table contains order details where cust_nbr represents the order number. I'm trying to find where if an order contains an item_nbr 90000, I need to know if the price for 90000 is greater than the sum of the other items plus tax. I have hundreds of thousands of records in this table. I am using Teradata.

CREATE TABLE Line_Item_Details_Tbl (
    cust_nbr INT,
    trn_dt DATE,
    str_typ VARCHAR(6),
    trn_nbr INT,
    item_nbr INT,
    price DECIMAL(6,2),
    tax DECIMAL(6,2)
);

Sample data:

INSERT INTO Line_Item_Details_Tbl VALUES 
  (5551, '12/22/2011',  'store', 215, 12345, 10.00, 1.25);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (5551, '12/22/2011',  'store', 215, 65715,  6.25, 0.75);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (5551, '12/22/2011',  'store', 215, 90000, 40.00, 0);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (6875, '12/10/2011', 'online', 856, 72345,  8.50, 1.00);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (6875, '12/10/2011', 'online', 856, 65715,  6.25, 0.75);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (3500, '12/12/2011',  'store', 402, 54123, 45.00, 4.00);
INSERT INTO Line_Item_Details_Tbl VALUES 
  (3500, '12/12/2011',  'store', 402, 90000, 20.00, 0);
INSERT INTO Line_Item_Details_Tbl VALUES 

The query should do the following:

Select cust_nbr, trn_dt, trn_nbr, sum(price + tax) as purchase
  For a cust_nbr with str_typ  = 'store' AND contains an item_nbr = 90000,
  aggregate price + tax for all items related to cust_nbr except item_nbr 90000

So, preliminary result should be:

cust_nbr  :   trn_dt   : trn_nbr : purchase
5551        12/22/2011   215       $18.25           
3500        12/12/2011   402       $49.00           

Then, for each record in the preliminary results, I need to subtract the price of item_nbr 90000 from the purchase and return results only if the purchase is less than
the price of item_nbr 90000 as net_cb

So, my ending result should be:

cust_nbr  trn_dt       trn_nbr  net_cb
  5551    12/22/2011   215      ($21.75)            

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

丑丑阿 2024-12-30 08:25:18

使用子查询来识别您想要的事务,然后使用 CASE 来确定哪些记录对您的聚合有贡献。

SELECT
  transactions.cust_nbr,
  transactions.trn_dt,
  transactions.trn_nbr,
  sum(price + tax)                                            AS total,
  sum(CASE WHEN item_nbr = 9000 THEN 0 ELSE price + tax END)  AS total_less_9000
FROM
(
  SELECT
    cust_nbr, trn_dt, trn_nbr
  FROM
    yourTable
  WHERE
    str_typ  = 'store'
    AND item_nbr = 90000
  GROUP BY
    cust_nbr, trn_dt, trn_nbr
)
  AS transactions
INNER JOIN
  yourTable
    ON  transactions.cust_nbr = yourTable.cust_nbr
    AND transactions.trn_dt   = yourTable.trn_dt
    AND transactions.trn_nbr  = yourTable.trn_nbr
GROUP BY
  transactions.cust_nbr, transactions.trn_dt, transactions.trn_nbr

或者简单地使用 HAVING 子句来确定要包含哪些事务。

SELECT
  cust_nbr,
  trn_dt,
  trn_nbr,
  sum(price + tax)                                            AS total,
  sum(CASE WHEN item_nbr = 9000 THEN 0 ELSE price + tax END)  AS total_less_9000
FROM
  yourTable
GROUP BY
  cust_nbr,
  trn_dt,
  trn_nbr
HAVING
  MAX(CASE WHEN item_nbr = 9000 THEN 1 ELSE 0 END) = 1

或者...

HAVING
  EXISTS (SELECT * FROM yourTable AS lookup
          WHERE cust_nbr = yourTable.cust_nbr
            AND trn_dt   = yourTable.trn_dt
            AND trn_nbr  = yourTable.trn_nbr
            AND item_nbr = 9000
         )

Use a sub-query to identify the transaction you want, then use CASE to determin which records contribute to you aggregates or not.

SELECT
  transactions.cust_nbr,
  transactions.trn_dt,
  transactions.trn_nbr,
  sum(price + tax)                                            AS total,
  sum(CASE WHEN item_nbr = 9000 THEN 0 ELSE price + tax END)  AS total_less_9000
FROM
(
  SELECT
    cust_nbr, trn_dt, trn_nbr
  FROM
    yourTable
  WHERE
    str_typ  = 'store'
    AND item_nbr = 90000
  GROUP BY
    cust_nbr, trn_dt, trn_nbr
)
  AS transactions
INNER JOIN
  yourTable
    ON  transactions.cust_nbr = yourTable.cust_nbr
    AND transactions.trn_dt   = yourTable.trn_dt
    AND transactions.trn_nbr  = yourTable.trn_nbr
GROUP BY
  transactions.cust_nbr, transactions.trn_dt, transactions.trn_nbr

Or simply use the HAVING clause to determine which transactions to include.

SELECT
  cust_nbr,
  trn_dt,
  trn_nbr,
  sum(price + tax)                                            AS total,
  sum(CASE WHEN item_nbr = 9000 THEN 0 ELSE price + tax END)  AS total_less_9000
FROM
  yourTable
GROUP BY
  cust_nbr,
  trn_dt,
  trn_nbr
HAVING
  MAX(CASE WHEN item_nbr = 9000 THEN 1 ELSE 0 END) = 1

Or...

HAVING
  EXISTS (SELECT * FROM yourTable AS lookup
          WHERE cust_nbr = yourTable.cust_nbr
            AND trn_dt   = yourTable.trn_dt
            AND trn_nbr  = yourTable.trn_nbr
            AND item_nbr = 9000
         )
等待圉鍢 2024-12-30 08:25:18

我已经在 SQL Server 2005 上进行了测试,所以如果它根本不起作用,请不要投票,请告诉我,我将删除我的答案:-)。我只是想帮忙。

将此视为您的示例数据(SQL Server 2005 中的 CTE):

;with ord_det (cust_nbr, trn_dt, str_typ, trn_nbr, item_nbr, price, tax) as (
    select 5551, convert(datetime, '12/22/2011', 101), 'store', 215, 12345, 10.00, 1.25  union all
    select 5551, convert(datetime, '12/22/2011', 101), 'store', 215, 65715, 6.25, 0.75  union all
    select 5551, convert(datetime, '12/22/2011', 101), 'store', 215, 90000, 40.00, null union all
    select 6875, convert(datetime, '12/10/2011', 101), 'online', 856, 72345, 8.50, 1.00  union all
    select 6875, convert(datetime, '12/10/2011', 101), 'online', 856, 65715, 6.25, 0.75  union all
    select 3500, convert(datetime, '12/12/2011', 101), 'store', 402, 54123, 45.00, 4.00  union all
    select 3500, convert(datetime, '12/12/2011', 101), 'store', 402, 90000, 20.00, null
)

最终查询(我假设您的表名称是 ord_det,如果它不只是使用正确的名称):

select t.cust_nbr, t.trn_dt, t.trn_nbr, price - purchase as net_cb from (
    select cust_nbr, trn_dt, trn_nbr, sum(price + coalesce(tax, 0)) as purchase
    from ord_det o
    where item_nbr <> 90000 and str_typ  = 'store'
    group by cust_nbr, trn_dt, trn_nbr
) t
inner join (
    select cust_nbr, trn_dt, trn_nbr, price + coalesce(tax, 0) as price
    from ord_det o
    where item_nbr = 90000 and str_typ  = 'store'
) t1 on t.cust_nbr = t1.cust_nbr
where purchase < price

结果:

cust_nbr    trn_dt                  trn_nbr     net_cb
5551        2011-12-22 00:00:00.000 215         21.75

I've tested in on SQL Server 2005 so please do not downvote if it doesn't work at all, just let me know and I will delete my answer :-). I'm just trying to help.

Treat this as your sample data (CTE in SQL Server 2005):

;with ord_det (cust_nbr, trn_dt, str_typ, trn_nbr, item_nbr, price, tax) as (
    select 5551, convert(datetime, '12/22/2011', 101), 'store', 215, 12345, 10.00, 1.25  union all
    select 5551, convert(datetime, '12/22/2011', 101), 'store', 215, 65715, 6.25, 0.75  union all
    select 5551, convert(datetime, '12/22/2011', 101), 'store', 215, 90000, 40.00, null union all
    select 6875, convert(datetime, '12/10/2011', 101), 'online', 856, 72345, 8.50, 1.00  union all
    select 6875, convert(datetime, '12/10/2011', 101), 'online', 856, 65715, 6.25, 0.75  union all
    select 3500, convert(datetime, '12/12/2011', 101), 'store', 402, 54123, 45.00, 4.00  union all
    select 3500, convert(datetime, '12/12/2011', 101), 'store', 402, 90000, 20.00, null
)

Final query (I assumed that your table name is ord_det, if it's not just use proper name):

select t.cust_nbr, t.trn_dt, t.trn_nbr, price - purchase as net_cb from (
    select cust_nbr, trn_dt, trn_nbr, sum(price + coalesce(tax, 0)) as purchase
    from ord_det o
    where item_nbr <> 90000 and str_typ  = 'store'
    group by cust_nbr, trn_dt, trn_nbr
) t
inner join (
    select cust_nbr, trn_dt, trn_nbr, price + coalesce(tax, 0) as price
    from ord_det o
    where item_nbr = 90000 and str_typ  = 'store'
) t1 on t.cust_nbr = t1.cust_nbr
where purchase < price

Result:

cust_nbr    trn_dt                  trn_nbr     net_cb
5551        2011-12-22 00:00:00.000 215         21.75
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文