[英]How to generate unique id for pair strings on certain conditions in MySQL
我是SQL的新手,请帮我解决问题。
我有一个网站的网站私人消息,我在引擎之间迁移后得到(phpbb到drupal)
可以说,它有3列:
每条消息都显示在收件人和邮箱的邮箱中,因此每封邮件都有2个字符串。
问题是消息的线程 ID不正确(基本上,它们等于mid ),因此2个用户之间的对应关系显示为一百个单独的线程。
例如:
user 100 wrote message to user 101
user 101 replied to user 100
user 102 wrote message to user 100
该表看起来像:
________________________________
| mid | thread | recipient |
| | | |
| 1 | 1 | 101 | ← message 1 in recipient's mailbox
| 1 | 1 | 100 | ← message 1 in author's mailbox
| 2 | 2 | 100 | ...
| 2 | 2 | 101 |
| 3 | 3 | 100 |
| 3 | 3 | 102 |
|________|___________|___________|
我的目标是为每组配对行提供相同的线程ID,并使用同一对收件人:
________________________________
| mid | thread | recipient |
| | | |
| 1 | 1 | 101 | }
| 1 | 1 | 100 | } Correspondence between 100 and 101 must
| 2 | 1 | 100 | } have the same thread id (1)
| 2 | 1 | 101 | }
| 3 | 2 | 100 |
| 3 | 2 | 102 |
|________|___________|___________|
对于同一收件人对之间的所有当前对话,线程ID必须相同。 (不要担心进一步的对话,用户可以选择在编写消息时打开新线程,这将生成新的线程ID,或者在现有线程中回复,这将标记具有现有线程ID的消息。我想要的只是聚集线程中每2个用户之间存在大量现有消息)。
我想像某种循环一样,它将搜索每个中间的所有收件人id,并在升序排序后将它们合并到数组中:
然后给出相同的数组,这将是我想要的线程ID:
不确定,如果我的算法只能用SQL查询
应该从您的应用程序更好地处理这种更正,因为它比在这个功能样式Sql更容易处理逻辑。
这是完成它的一种方法( 这假设所有相关(线程)对话一个接一个地进行,如您已确认 ):
SELECT mid,
thread,
recipient
FROM (
SELECT row,
mid,
recipient,
IF(row % 2 = 0, @evenThread := thread, NULL) AS tempThread,
IF(row % 2 = 1, @evenThread, thread) AS thread
FROM (
SELECT @row := @row + 1 as row,
mid,
IF(@row = 1, @thread := thread, NULL) AS tempThread,
IF(@row % 2 = 1, IF(@row = 1, @rec1 := recipient, @rec1 := @rec3), NULL) AS tempOddRow,
IF(@row % 2 = 1, @rec3 := recipient, recipient) AS recipient,
IF(@row % 2 = 0 AND @row > 2, IF((recipient != @rec1 OR @rec3 != @rec2) AND (recipient != @rec2 OR @rec3 != @rec1), @isDifferent := true, @isDifferent := false), NULL) AS isDifferent,
IF(@row % 2 = 0, @rec2 := recipient, NULL) AS tempEvenRow,
IF(@row % 2 = 0, IF(@isDifferent, @thread := @thread + 1, @thread), @thread) AS thread
FROM (SELECT @row := 0) AS r,
(SELECT @thread := 0) as t,
(SELECT @isDifferent := false) as d,
(SELECT @rec1 := 0) AS r1,
(SELECT @rec2 := 0) AS r2,
(SELECT @rec3 := 0) AS r3,
messages --your table name
ORDER BY row DESC
) AS temp,
(SELECT @evenThread := 0) AS t
) AS corrected
ORDER BY row
这只是选择查询 。 在这里测试http://sqlfiddle.com/#!9/61247/2 。 您可以将其复制到临时表中,并首先确认所有数据是否正确,而不是更新原始表,这将使调试更加困难。 有点像:
CREATE TABLE messages_new LIKE messages; --new table name given
INSERT INTO messages_new (mid, thread, recipient)
SELECT mid,
thread,
recipient
FROM (
SELECT row,
mid,
recipient,
IF(row % 2 = 0, @evenThread := thread, NULL) AS tempThread,
IF(row % 2 = 1, @evenThread, thread) AS thread
FROM (
SELECT @row := @row + 1 as row,
mid,
IF(@row = 1, @thread := thread, NULL) AS tempThread,
IF(@row % 2 = 1, IF(@row = 1, @rec1 := recipient, @rec1 := @rec3), NULL) AS tempOddRow,
IF(@row % 2 = 1, @rec3 := recipient, recipient) AS recipient,
IF(@row % 2 = 0 AND @row > 2, IF((recipient != @rec1 OR @rec3 != @rec2) AND (recipient != @rec2 OR @rec3 != @rec1), @isDifferent := true, @isDifferent := false), NULL) AS isDifferent,
IF(@row % 2 = 0, @rec2 := recipient, NULL) AS tempEvenRow,
IF(@row % 2 = 0, IF(@isDifferent, @thread := @thread + 1, @thread), @thread) AS thread
FROM (SELECT @row := 0) AS r,
(SELECT @thread := 0) as t,
(SELECT @isDifferent := false) as d,
(SELECT @rec1 := 0) AS r1,
(SELECT @rec2 := 0) AS r2,
(SELECT @rec3 := 0) AS r3,
messages
ORDER BY row DESC
) AS temp,
(SELECT @evenThread := 0) AS t
) AS corrected
ORDER BY row;
DROP TABLE messages;
ALTER TABLE messages_new RENAME TO messages; --back to old name
我把它放到SQL小提琴中: http ://sqlfiddle.com/#!2/83bdc/25
假设你的表名是messages
那么这就是我要做的:
Select messages.*, FirstThread
From messages
Inner Join
(
-- Find a pair of dudes for each message and show the earliest thread of each
Select ThreadsForPairs.*, FirstThread From
(
Select mid
, Min(recipient) AS FirstDude
, Max(recipient) AS SecondDude
, thread
From messages
Group By mid, thread
) ThreadsForPairs
Left Join
(
-- Find the earliest thread for every pair of dudes
Select FirstDude, SecondDude, Min(thread) AS FirstThread
From
-- For every message, get the dudes involved
(
Select mid
, Min(recipient) AS FirstDude
, Max(recipient) AS SecondDude
, thread
From messages
Group By mid, thread
) PairsForMessages
Group By FirstDude, SecondDude
) FirstThreadForPairs
ON ThreadsForPairs.FirstDude = FirstThreadForPairs.FirstDude
AND ThreadsForPairs.SecondDude = FirstThreadForPairs.SecondDude
) FirstThreadForEveryMessage
On messages.mid = FirstThreadForEveryMessage.mid
正如您将看到的,我不完全匹配您的输出,因为消息ID 3将具有线程3而不是2,但我认为它是相同的想法......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.