【问题标题】:min and count without limit最小和无限制计数
【发布时间】:2020-07-25 10:01:39
【问题描述】:

我需要选择具有 3 个条件的收据:

  1. 总收据 > 50 (receipt.total)
  2. 相关购买不包括商品“黄瓜”(product.pname)
  3. 关联产品的供应商数量(product.sid)最少

我设置了以下表格:

Receipt (bid, rdate, rtime, ptype, total)
Purchase (bid, rdate, rtime, code, units)
Product (code, pname, descr, utype, uprice, manu, sid)

样本数据:

INSERT INTO Product (code, pname, descr, utype, uprice, manu, sid) VALUES
        (987, 'Tomatoes',       'Vegetable',  'Kg',  5.99,  'manufacturer1', 111),
        (876, 'Cucumbers',      'Vegetable',  'Kg',  4.99,  'manufacturer2', 222),
        (765, 'Cornflakes',     'Cornflakes', 'Box', 15.9,  'manufacturer2', 222),
        (654, 'Camembert',      'Cheese',     'Box', 12.50, 'manufacturer2', 111),
        (543, 'sweet potato',   'Vegetable',  'Kg',  16.40, 'manufacturer3', 333),
        (432, 'red pepper',     'Vegetable',  'Kg',  15.99, 'manufacturer1', 111);
INSERT INTO Receipt (bid, rdate, rtime, ptype, total) VALUES
        (989, '18/3/2020', '10:00', 'Cash', 126.51),
        (989, '16/7/2020', '12:30', 'Credit',0),
        (989, '15/7/2020', '15:35', 'Credit',0),
        (878, '17/3/2020', '8:30',  'Cash', 60.47),
        (878, '22/7/2020', '7:00',  'Credit',0),
        (767, '13/7/2020', '22:00', 'Cash',0),
        (767, '10/3/2020', '20:30', 'Cash',42.97),
        (767, '14/5/2020', '14:25', 'Credit',0);


INSERT INTO Purchase (bid, rdate, rtime, code, units) VALUES
        (989, '18/3/2020', '10:00', 987, 5),
        (989, '18/3/2020', '10:00', 876, 3),
        (989, '18/3/2020', '10:00', 543, 4),
        (989, '18/3/2020', '10:00', 432, 1),
        (878, '17/3/2020', '8:30',  654, 1),
        (878, '17/3/2020', '8:30',  432, 3),
        (767, '10/3/2020', '20:30', 654, 2),
        (767, '10/3/2020', '20:30', 987, 3);

到目前为止,我有以下内容,但没有收到 sid 数量最少的收据:

SELECT Receipt.rdate, Receipt.rtime, Receipt.bid
FROM Receipt NATURAL JOIN Purchase NATURAL JOIN Product
WHERE total > 50 and 
NOT EXISTS(
    SELECT * FROM Product NATURAL JOIN Purchase
    WHERE Receipt.bid = Purchase.bid and Receipt.rdate = Purchase.rdate and Receipt.rtime = Purchase.rtime and Product.code = '876')
GROUP BY Receipt.rdate, Receipt.rtime, Receipt.bid
HAVING COUNT(DISTINCT Product.sid) = (SELECT MIN(mycount) 
FROM (SELECT sid,COUNT(DISTINCT Product.sid) mycount from product group by product.sid) ct);

我不允许使用 order by 和 limit。我做错了什么?

【问题讨论】:

  • 考虑使用有意义的列名。
  • 我不明白第三个条件是指计数还是最低 sid 中​​的数字,请添加预期输出。
  • 您真正使用的是哪个数据库?? mysql 还是 postgresql ???
  • 我正在使用 postgresql。我需要以最少的唯一 sid 数获得收据。带有样本数据的预期输出将是“878, '17/3/2020', '8:30'”,因为此收据仅关联 1 个 sid
  • 我不能使用 order by 和 limit。 为什么? A 中的 Gordon 的 Order By/Limit 可以替换为 Row_Number = 1

标签: sql postgresql group-by


【解决方案1】:

没有订购者:

with cte as 
 ( SELECT Receipt.rdate, Receipt.rtime, Receipt.bid,
      COUNT(DISTINCT Product.sid) as cnt, -- count per bid
      MIN(COUNT(DISTINCT Product.sid))    -- minimum count over rows
      OVER () as min_count                -- PARTITION BY needed???
   FROM Receipt NATURAL JOIN Purchase NATURAL JOIN Product
   WHERE total > 50 and 
   NOT EXISTS(
       SELECT * FROM Product NATURAL JOIN Purchase
       WHERE Receipt.bid = Purchase.bid
         and Receipt.rdate = Purchase.rdate
         and Receipt.rtime = Purchase.rtime and Product.code = '876')
   GROUP BY Receipt.rdate, Receipt.rtime, Receipt.bid
 )
select *
from cte
where cnt = min_count

简化 NOT EXISTS 逻辑:

with cte as 
 ( SELECT Receipt.rdate, Receipt.rtime, Receipt.bid,
      COUNT(DISTINCT Product.sid) as cnt, -- count per bid
      MIN(COUNT(DISTINCT Product.sid))    -- minimum count over rows
      OVER () as min_count                -- PARTITION BY needed???
   FROM Receipt NATURAL JOIN Purchase NATURAL JOIN Product
   WHERE total > 50 
   GROUP BY Receipt.rdate, Receipt.rtime, Receipt.bid
   -- will be > 0 when cucumbers exist
   HAVING count(case when product.pname = 'cucumbers' then 1 end) = 0
 )
select *
from cte
where cnt = min_count

【讨论】:

    【解决方案2】:

    这对我来说似乎是一个聚合查询:

    select p.bid, p.rdate, p.rtime, sum(pr.price * p.units), count(distinct pr.sid) as num_suppliers
    from purchase p join
         products pr
         on pr.code = p.code
    group by p.bid, p.rdate, p.rtime
    having count(*) filter (where pr.name = 'cucumbers') = 0 and
           sum(pr.price * p.units) > 50
    order by count(distinct pr.sid) asc
    limit 1;
    

    我看到您的数据模型确实有 total,但没有您的数据。在这种情况下:

    select p.bid, p.rdate, p.rtime, sum(pr.price * p.units), count(distinct pr.sid) as num_suppliers
    from purchase p join
         products pr
         on pr.code = p.code join
         receipt r
         on r.bid = p.bid and r.rdate = p.rdate and r.rtime = p.rtime
    where r.total > 50
    group by p.bid, p.rdate, p.rtime
    having count(*) filter (where pr.name = 'cucumbers') = 0 
    order by count(distinct pr.sid) asc
    limit 1;
    

    【讨论】:

    • 谢谢!但我不允许使用 order by 和 limit(在问题中提到......)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 2018-10-15
    • 2020-10-09
    • 1970-01-01
    相关资源
    最近更新 更多