简体   繁体   English

按字段对记录进行分组并在 sql 中提交对每个组的查询

[英]grouping records by a field and submit a query on each group in sql

I have a table like this:我有一张这样的表:

create table product_company (
    id int PRIMARY KEY,
    productName varchar(100),
    companyName varchar(100),
    price int
);

I want to know the name of the product which it has the second rank in price in each company.我想知道它在每个公司中价格排名第二的产品名称。

for example if company1 has three product product1=30 , product2=50 and product3=15 (the assignment shows the price of each product in this company) so product1 has the second rank in price property in company1 and I want to write a query that returns something like below:例如,如果company1有三个产品product1=30product2=50product3=15 (分配显示该公司每个产品的价格),那么product1company1价格属性中排名第二,我想写一个查询返回如下内容:

company1 product1
company2 ...
...

I mean for every company I want to know the product that has the second rank in price within that company.我的意思是对于每家公司,我都想知道在该公司中价格排名第二的产品。 I don't know how to use group by clause because group by is working fine by aggregate functions but I don't want the maximum in price.我不知道如何使用 group by 子句,因为 group by 可以通过聚合函数正常工作,但我不想要最高价格。

I want to write this query with standard sql queries and clauses and without some special funcions that may not work in some DBMS我想用标准的 sql 查询和子句编写这个查询,并且没有一些可能在某些 DBMS 中不起作用的特殊函数

If you are running MySQL 8.0, you can use window function dense_rank() :如果您运行的是 MySQL 8.0,则可以使用窗口函数dense_rank()

select *
from (
    select
        pc.*,
        dense_rank() over(partition by companyName order by price desc) rn
    from product_company pc
) t
where rn = 2

In earlier versions, one solution is to filter with a correlated subquery.在早期版本中,一种解决方案是使用相关子查询进行过滤。 But you have to be careful to properly handle possible top ties.但是您必须小心正确处理可能的顶级关系。 This should do it:这应该这样做:

select pc.*
from product_company pc
where (
    select count(distinct pc1.price) 
    from product_company pc1 
    where pc1.companyName = pc.companyName and pc1.price > pc.price
) = 1

An EXISTS with a COUNT can also be used for this带有 COUNT 的 EXISTS 也可用于此

For example:例如:

 create table product_company ( id int PRIMARY KEY AUTO_INCREMENT, productName varchar(100), companyName varchar(100), price decimal(16,2) );
 insert into product_company (productName, companyName, price) values ('product 1', 'odd org', 9) ,('product 2', 'odd org', 15) ,('product 3', 'odd org', 11) ,('product 4', 'odd org', 17) ,('product 5', 'even inc.', 18) ,('product 6', 'even inc.', 12) ,('product 7', 'even inc.', 16) ,('product 8', 'even inc.', 14) ;
 select * from product_company t where exists ( select 1 from product_company t2 where t2.companyName = t.companyName and t2.price >= t.price having count(distinct t2.price) = 2 )
\nid |身份证 | productName |产品名称 | companyName |公司名称 | price价钱\n-: | -: | :---------- | :---------- | :---------- | :---------- | ----: ----:\n 2 | 2 | product 2 |产品 2 | odd org |奇怪的组织| 15.00 15.00\n 7 | 7 | product 7 |产品 7 | even inc.甚至公司| | 16.00 16.00\n

db<>fiddle here db<> 在这里摆弄

And if you want to have the top 2 per company?如果您想拥有每家公司的前 2 名?
Then change the HAVING clause然后更改HAVING子句

...
   having count(distinct t2.price) <= 2
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM