2011-09-22 35 views
5

Tôi có một nhóm người dùng trong cơ sở dữ liệu của mình và tôi muốn đặt lại tất cả tên người dùng của họ thành chữ cái đầu tiên của tên của họ, cộng với họ đầy đủ của họ. Như bạn có thể tưởng tượng, có một số lừa đảo. Trong trường hợp này, tôi muốn thêm "2" hoặc "3" hoặc thứ gì đó vào cuối tên người dùng. Làm cách nào để viết truy vấn để tạo tên người dùng duy nhất như thế này?Tạo tên người dùng duy nhất từ ​​họ và tên?

UPDATE user 
SET username=lower(concat(substring(first_name,1,1), last_name), UNIQUETHINGHERE) 

Trả lời

5
CREATE TABLE bar LIKE foo; 

INSERT INTO bar (id,user,first,last) 
(SELECT f.id,CONCAT(SUBSTRING(f.first,1,1),f.last, 
    (SELECT COUNT(*) FROM foo f2 
     WHERE SUBSTRING(f2.first,1,1) = SUBSTRING(f.first,1,1) 
       AND f2.last = f.last AND f2.id <= f.id 
     )),f.first,f.last from foo f); 

DROP TABLE foo; 
RENAME TABLE bar TO foo; 

này dựa trên một khóa chính id, vì vậy cho mỗi bản ghi chèn vào bar, chúng tôi chỉ tính trùng được tìm thấy trong foo với id ít hơn bar.id.

foo Given:

select * from foo; 
+----+------+--------+--------+ 
| id | user | first | last | 
+----+------+--------+--------+ 
| 1 | aaa | Roger | Hill | 
| 2 | bbb | Sally | Road | 
| 3 | ccc | Fred | Mount | 
| 4 | ddd | Darren | Meadow | 
| 5 | eee | Sharon | Road | 
+----+------+--------+--------+ 

Trên đây INSERT s vào bar, kết quả là:

select * from bar; 
+----+----------+--------+--------+ 
| id | user  | first | last | 
+----+----------+--------+--------+ 
| 1 | RHill1 | Roger | Hill | 
| 2 | SRoad1 | Sally | Road | 
| 3 | FMount1 | Fred | Mount | 
| 4 | DMeadow1 | Darren | Meadow | 
| 5 | SRoad2 | Sharon | Road | 
+----+----------+--------+--------+ 

Để loại bỏ các "1" từ ngày kết thúc của tên người dùng,

INSERT INTO bar (id,user,first,last) 
(SELECT f3.id, 
     CONCAT(
      SUBSTRING(f3.first,1,1), 
      f3.last, 
      CASE f3.cnt WHEN 1 THEN '' ELSE f3.cnt END), 
     f3.first, 
     f3.last 
FROM (
    SELECT 
     f.id, 
     f.first, 
     f.last, 
     (
      SELECT COUNT(*) 
      FROM foo f2 
      WHERE SUBSTRING(f2.first,1,1) = SUBSTRING(f.first,1,1) 
      AND f2.last = f.last AND f2.id <= f.id 
     ) as cnt 
    FROM foo f) f3) 
+0

thanh gì? tại sao có dấu ngoặc kép ở cuối? quan tâm để giải thích điều này một chút? – mpen

+0

@Mark: 'bar' là một bảng trống như' foo'. Sau khi chèn các bản ghi vào 'bar', bạn có thể thả' foo' và đổi tên 'bar' ->' foo'. Trích dẫn ba là một tạo phẩm của Python, nơi tôi đã kiểm tra mã. – unutbu

+0

Ah. Tôi chỉ muốn cập nhật bảng người dùng, nhưng tôi đoán tôi có thể dễ dàng chuyển nó trở lại. Đó là khá mát mẻ. Tôi cũng sẽ để lại số nếu nó là "1", nhưng một lần nữa, điều đó phải dễ dàng để làm. Tốt đẹp! Cảm ơn rất nhiều! ** Chỉnh sửa: ** Giống như bình luận của bạn giải thích. – mpen

3

Là một hai parter:

SELECT max(username) 
FROM user 
WHERE username LIKE concat(lower(concat(substring(first_name,1,1),lastname), '%') 

để lấy tên người dùng "cao nhất" cho rằng tên combo. Giải nén hậu tố số, tăng nó, sau đó chèn lại vào cơ sở dữ liệu cho người dùng mới của bạn.

Điều này là đáng tiếc, tất nhiên. Hai người dùng có cùng tên/họ có thể dẫm lên tên người dùng của nhau, tùy thuộc vào cách mọi thứ diễn ra. Bạn chắc chắn muốn rắc một số giao dịch/khóa vào các truy vấn để đảm bảo bạn không có bất kỳ người dùng nào xung đột.

+0

Tôi đã hy vọng để làm điều này với MySQL tinh khiết ... điều này sẽ yêu cầu tôi để lặp qua tất cả người dùng, phải không? – mpen

0

Neve rmind .... Tôi vừa tìm thấy các bản dupes:

select LOWER(CONCAT(SUBSTRING(first_name,1,1),last_name)) as new_login,count(*) as cnt from wx_user group by new_login having count(*)>1; 

Và đặt chúng theo cách thủ công. Chỉ là một số ít.

1

Lấy cảm hứng từ trong câu trả lời của unutbu: không có nhu cầu để tạo ra một bảng phụ không nhiều truy vấn:

UPDATE USER a 
    LEFT JOIN (
     SELECT USR_ID, 
      REPLACE(
       CONCAT(
        SUBSTRING(f.`USR_FIRSTNAME`,1,1), 
        f.`USR_LASTNAME`, 
        (
         (SELECT IF(COUNT(*) > 1, COUNT(*), '') 
          FROM USER f2 
          WHERE SUBSTRING(f2.`USR_FIRSTNAME`,1,1) = 
           SUBSTRING(f.`USR_FIRSTNAME`,1,1) 
           AND f2.`USR_LASTNAME` = f.`USR_LASTNAME` 
           AND f2.`USR_ID` <= f.`USR_ID`) 
         ) 
       ), 
       ' ', 
       '') as login 
     FROM USER f) b 
    ON a.USR_ID = b.USR_ID 
    SET a.USR_NICKNAME = b.login 
+0

Tôi đã cố hết sức để thêm đủ thụt lề vào điều này để làm cho điều này có thể đọc được, nhưng truy vấn này là một chút của một con quái vật theo cách nó được viết. –

+0

Tại sao lại là downvote? Nó có thể là quái dị nhưng nó hoạt động và nó có thể giúp mọi người, tôi đã có cùng một vấn đề và đây là giải pháp tôi tìm thấy, downvoting này cho ý tưởng rằng điều này là sai! – Batato

+0

Tôi đã không downvote nó, nhưng như ban đầu trả lời, thiếu indentation làm cho nó không thể đọc được. Tôi cược đó là lý do tại sao. [Nhưng hỏi "Tại sao downvote?" thường được coi là kiểu xấu ở đây.] (http: //meta.stackoverflow.com/questions/252826/is-ask-why-for-downvote-in-comments-không có tính xây dựng) –

Các vấn đề liên quan