我这里有一些mysql查询的问题。我知道如何修复它,但我想知道是否有更快更好的解决方案。 (我确定有。)
这就是我的表格的样子。
TABLE logger
id keys text type_id
1 2csi consectetuer 1
2 3vjk lorem ipsum 2
3 2csi consectetuer 1
4 3vjk lorem ipsum 2
5 j49a consectetuer 1
我的记录器变得疯狂,记录的值键和文本作为单独的行。 90%使用正确的type_id。
TABLE broken_logger
id keys text type_id
1 consectetuer 1
2 0a2v 0
3 lorem ipsum 2
4 2csi 1
5 consectetuer 1
6 3vjk 2
7 lorem ipsum 2
8 3vjk 2
9 dolor sit amet 2
10 consectetuer 1
11 2csi 1
12 lorem ipsum 2
13 nibh euismod 1
14 consectetuer 1
15 7kl4 0
16 j49a 1
17 Ut wisi enim 1
18 volutpat 2
19 sed diam 1
20 7kl4 0
文本用于排序或合并无用,它用于以后的分析。所以它必须与具有相同type_id的键连接。 Type_id == 0是错误,应该被忽略。它只在带键的行中,没有文本行的type_id = 0。
我尝试了JOINS和UNION ALL,但老实说我不知道如何使用(OUTER | RIGHT | LEFT | CROSS)JOIN将一个键合并为一个文本。我总是为每个文本获取具有相同type_id的每个键。而且我不想将所有这些结合起来。只需将行与文本合并,而不使用带键但没有文本的行的键。
所以我尝试了这个脏程序:
BEGIN
DECLARE num INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE k INT DEFAULT 1;
DECLARE pid INT DEFAULT 0;
DECLARE pkey VARCHAR(4) DEFAULT '';
-- all type_ids
WHILE k <= 2 DO
-- select numer of keys for this type_id
SELECT count(*) INTO num
FROM broken_logger
WHERE type_id = k
AND text = ''
AND key != '';
WHILE i < num DO
-- select only one key for update and key id for later deletion
SELECT id, key INTO pid, pkey
FROM broken_logger
WHERE type_id = k
AND text = ''
AND key != ''
LIMIT 1;
-- update only one text entry with one key
UPDATE broken_logger
SET key = pkey
WHERE type_id = k
AND text != ''
AND key = ''
LIMIT 1;
-- delete used key
DELETE broken_logger
WHERE id = pid;
SET i = i + 1;
END WHILE;
SET i = 0;
SET k = k + 1;
END WHILE;
END;
它正在工作,但它无效且非常慢。我尝试了很多事情,我认为我是在圈子里跑。有人可以指点我或帮助JOINS / UNIONS让这个任务更干净吗?
答案 0 :(得分:1)
如果我理解你的问题,键和文本按类型顺序出现(虽然可能混合使用不同的类型,以便类型1键后面跟着类型2文本,然后键入1文本),你只需要一个有效的把他们加在一起的方式。
为了解决这个问题,我使用了我在另一个Stack Overflow问题(Ranking by Group in MySQL)上找到的MySQL排名函数,它允许我按类型ID排名。它通过type_id
对结果进行排序,然后递增cnt
直到type_id
更改为止。我从使用排名函数的查询中创建了两个表和密钥和文本表,然后将它们连接在一起以生成下面的结果。
<强> SQL 强>
SET @prev := 0;
SET @cnt := 1;
CREATE TABLE sequentialkeys AS (
SELECT id, `key`, type_id,
IF(@prev <> type_id, @cnt := 1, @cnt := @cnt + 1) AS rank, @prev := type_id
FROM logger
WHERE type_id != 0 AND `key` != ''
ORDER BY type_id, id
);
SET @prev := 0;
SET @cnt := 1;
CREATE TABLE sequentialtext AS (
SELECT id, `text`, type_id,
IF(@prev <> type_id, @cnt := 1, @cnt := @cnt + 1) AS rank, @prev := type_id
FROM logger
WHERE type_id != 0 AND `text` != ''
ORDER BY type_id, id
);
SET @cnt := 0;
SELECT @cnt := @cnt + 1 AS id, a.*
FROM (
SELECT k.key, t.text, t.type_id
FROM sequentialkeys AS k
INNER JOIN sequentialtext AS t ON t.type_id = k.type_id AND t.rank = k.rank
ORDER BY t.id
) AS a
<强>结果强>
ID KEY TEXT TYPE_ID
1 2csi consectetuer 1
2 3vjk lorem ipsum 2
3 2csi consectetuer 1
4 3vjk lorem ipsum 2
5 j49a consectetuer 1
sequentialkeys
和sequentialtext
。