简体   繁体   中英

MySQL SELECT increment counter if id already selected

I have a very simple MySQL table which structure is as follows :

id   | customer_id |  name  | address
-------------------------------
1    |      1      |  John  | 123 street
2    |      2      |  Jane  | 456 lane
3    |      1      |  John  | 789 square
4    |      1      |  John  | 000 street
5    |      3      |  Paul  | 666 hell

Each customer can have more than one address, i would like to select them all, with an incremented counter specific to each ID, as such :

id   | customer_id |  address   |    count_by_id
----------------------------------------------------
1    |      1      | 123 street |  John's address #1
2    |      2      | 456 lane   |  Jane's address #1
3    |      1      | 789 square |  John's address #2
4    |      1      | 000 street |  John's address #3
5    |      3      | 666 hell   |  Paul's address #1

How may I proceed ?

SELECT x.*
     , COUNT(*) rank 
  FROM customer_address x 
  JOIN customer_address y 
    ON y.customer_id = x.customer_id 
   AND y.customer_address_id <= x.customer_address_id 
 GROUP 
    BY x.customer_id
     , x.customer_address_id 
 ORDER 
    BY customer_address_id;

If performance is an issue, we can talk about that (or just see @kickstart's answer)

  1. You can use subquery to get number of addresses with the same customer_id as current address has, but smaller id than current address has .

    Suppose your table (or view) is named address_table . Then:

     SELECT a.id, a.customer_id, a.name, a.address, (SELECT count(*) FROM address_table WHERE customer_id=a.customer_id and id<a.id)+1 AS count_by_id FROM address_table AS a; 
  2. Another solution, which is harder to understand but still valid, is to use JOIN+GROUPBY:

    Just see Strawberry's answer.

Not tested, but 2 methods below.

firstly by using a sequence number to count up the values.

SELECT id, customer_id, address, CONCAT(name, "'s address #", addr_seq)
FROM 
(
    SELECT id, customer_id, name, address, @counter:=IF(@prev_customer_id = customer_id, @counter + 1, 1) AS addr_seq, @prev_customer_id := customer_id
    FROM address_table
    CROSS JOIN (SELECT @counter:= 0, @prev_customer_id:=0) Sub1
    ORDER BY customer_id, id
) Sub2
ORDER BY id

Or using join and count

SELECT id, customer_id, address, CONCAT(name, "'s address #", addr_seq)
FROM 
(
    SELECT a.id,a. customer_id, a.address, COUNT(b.id) AS addr_seq
    FROM address_table a
    INNER JOIN address_table b
    WHERE a.customer_id = b.customer_id
    AND a.id >= b.id
    GROUP BY a.id,a. customer_id, a.address
) Sub1
ORDER BY id

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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