简体   繁体   English

为什么count(column_name)的行为如此?

[英]Why is count(column_name) behaving like this?

Consider the relation account (customer, balance) where customer is a primary key and there are no null values. 考虑客户是主键且没有空值的关系帐户(客户,余额)。

I would like to rank customers according to decreasing balance. 我想根据余额减少对客户进行排名。 (The customer with the largest balance gets rank 1. Ties are not broke but ranks are skipped: if exactly two customers have the largest balance they each get rank 1 and rank 2 is not assigned.) (具有最大余额的客户获得等级1。并没有打破关系,但跳过了等级:如果恰好有两个客户具有最大余额,则他们每个都获得等级1和等级2。)

Why does the following query never prints the customer having rank 1? 为什么以下查询从不打印排名为1的客户?

    select A.customer, 1+count(B.customer) 
    from account A, account B 
    where A.balance < B.balance 
    group by A.customer 

SQLfiddle Link SQLfiddle链接

Let's try this Example 让我们尝试这个例子

Ranking without skipping a rank 排名不跳过排名

set @number:=0;
set @balance:=0;

select customer, balance, rank 
from (
  select 
    *, 
    @number:=if(@balance=balance, @number, @number+1) as rank,
    @balance:=balance
  from account
  order by balance
) as rankeddata;

Result 结果

customer balance rank
S        300     1
Q        400     2
R        400     2
P        500     3

To show ranking from 500 -> 300, just change the ORDER BY balance to ORDER BY balance DESC 要显示排名从500-> 300,只需将ORDER BY balance更改为ORDER BY balance DESC

Skip rank if multiple rows have same rank 如果多行具有相同的等级,则跳过等级

If you prefer to skip an assigned rank, you can tweak the query a little bit SQL Fiddle . 如果您希望跳过分配的排名,则可以对查询进行一些调整,例如SQL Fiddle

set @number:=0;
set @balance:=0;
set @rank_reused:=0;

select customer, balance, rank
from (
  select 
    *, 
    @number:=if(@balance=balance, @number, @number+1+@rank_reused) as rank,
    @rank_reused:=if(@balance=balance, @rank_reused+1, 0) as reused,
    @balance:=balance
  from account
  order by balance desc
) as rankeddata;

Result 结果

customer balance rank
S        300     1
Q        400     2
R        400     2
P        500     4

This has nothing to do with the count. 这与计数无关。

You are doing a join between A and B and show only the records where A.balance < B.balance since there is no such record for your top rank customer (by definition there is no account with higher balance) you don't get any record. 您正在进行A和B之间的联接,并且只显示A.balance <B.balance的记录,因为您的顶级客户没有这样的记录(根据定义,没有余额更高的帐户)记录。

This should do the trick 这应该可以解决问题

select A.customer, ( 
    select count(*) + 1 
    from account B
    where A.balance < B.balance
) from account A

The following statement will give you a rank of all customers based on their balance: 以下语句将根据您的余额为您列出所有客户的排名:

SELECT A.customer, A.balance, ( 
    SELECT count(*)+1 
    FROM account B
    WHERE A.balance < B.balance
  ) AS rank
FROM account A ORDER BY A.balance DESC

The result will be: 结果将是:

customer balance rank
P   500 1 
Q   400 2 
R   400 2 
S   300 4

order by A.balance does the ordering, while desc ranks from largest to smallest. order by A.balance进行排序,而desc从大到小排列。 Lastly, the subquery provides the rank (note the +1). 最后,子查询提供了排名(请注意+1)。

Here's an the example fiddle . 这是一个小提琴的例子。

Try 尝试

select A.customer, 
(select count(*) from account) -
(select count(*) from account a1 where a1.balance<a.balance) rank
from account A
Order by rank

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

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