-1

我有两张这样的桌子:

summary(id, status, value, time, aperson) and long_summary(id, who, comment, alltext)

为此,我尝试了以下查询,例如:

SELECT l.id,summary.status
FROM  long_summary l INNER JOIN summary ON l.id = summary.id INNER JOIN long_summary ON summary.aperson = long_summary.who 
WHERE summary.status IN('old','new','waiting')
AND summary.value IN ('') 
AND summary.time >= DATE_SUB(NOW(),INTERVAL 2 MONTH)
AND l.alltext LIKE '% relational database management system %' ORDER BY FIELD(summary.status,'old','new','waiting'),summary.time DESC

运行时它会给出正确的输出,但返回的行会多次出现,例如:

(1,'old')
(1,'old')
(1,'old')
(2,'new')
(2,'new')
(3,'new')
(4,'waiting')
(4,'waiting')

为此i have used SELECT DISTINCT and after that it is giving correct output without repetition of the single row。但我没有得到我做错了什么?你会建议吗?

4

1 回答 1

1

The way to see what's happening is to (a) create a stripped-down test case, and (b) do a SELECT * so you can see what you're getting back in the other columns, that's causing the repetition.

So, I did this:

CREATE TABLE summary(id, status, value, time, aperson);
INSERT INTO "summary" VALUES(1,'old',23,'time0','joe');
INSERT INTO "summary" VALUES(2,'new',42,'time1','bob');
INSERT INTO "summary" VALUES(3,'new',32,'time2','mike');
CREATE TABLE long_summary(id, who, comment, alltext);
INSERT INTO "long_summary" VALUES(1,'someone','i say!','some text');
INSERT INTO "long_summary" VALUES(1,'joe','joe likes','some text');
INSERT INTO "long_summary" VALUES(2,'joe','joe likes bob','some text');
INSERT INTO "long_summary" VALUES(3,'joe','joe likes mike','some text');
INSERT INTO "long_summary" VALUES(1,'bob','nice one, joe','some text');
INSERT INTO "long_summary" VALUES(2,'bob','nice one, me','some text');
INSERT INTO "long_summary" VALUES(2,'bob','double nice one, me','some text');
INSERT INTO "long_summary" VALUES(3,'bob','nice one, mike','some text');
COMMIT;

Then I took a simpler version of your query:

SELECT l.id,summary.status
FROM  long_summary l INNER JOIN summary ON l.id = summary.id INNER JOIN long_summary ON summary.aperson = long_summary.who 
WHERE summary.status IN('old','new','waiting')

None of the other stuff could make things any worse, right? So it's irrelevant. What do I get when I run this? 9 copies of 1|old, and 12 copies of 2|new.

So, let's change it to see the whole row:

SELECT *
FROM  long_summary l INNER JOIN summary ON l.id = summary.id INNER JOIN long_summary ON summary.aperson = long_summary.who 
WHERE summary.status IN('old','new','waiting')

1|bob|nice one, joe|some text|1|old|23|time0|joe|1|joe|joe likes|some text
1|bob|nice one, joe|some text|1|old|23|time0|joe|2|joe|joe likes bob|some text
1|bob|nice one, joe|some text|1|old|23|time0|joe|3|joe|joe likes mike|some text
1|joe|joe likes|some text|1|old|23|time0|joe|1|joe|joe likes|some text
1|joe|joe likes|some text|1|old|23|time0|joe|2|joe|joe likes bob|some text
1|joe|joe likes|some text|1|old|23|time0|joe|3|joe|joe likes mike|some text
1|someone|i say!|some text|1|old|23|time0|joe|1|joe|joe likes|some text
1|someone|i say!|some text|1|old|23|time0|joe|2|joe|joe likes bob|some text
1|someone|i say!|some text|1|old|23|time0|joe|3|joe|joe likes mike|some text
2|bob|double nice one, me|some text|2|new|42|time1|bob|1|bob|nice one, joe|some text
2|bob|double nice one, me|some text|2|new|42|time1|bob|2|bob|double nice one, me|some text
2|bob|double nice one, me|some text|2|new|42|time1|bob|2|bob|nice one, me|some text
2|bob|double nice one, me|some text|2|new|42|time1|bob|3|bob|nice one, mike|some text
2|bob|nice one, me|some text|2|new|42|time1|bob|1|bob|nice one, joe|some text
2|bob|nice one, me|some text|2|new|42|time1|bob|2|bob|double nice one, me|some text
2|bob|nice one, me|some text|2|new|42|time1|bob|2|bob|nice one, me|some text
2|bob|nice one, me|some text|2|new|42|time1|bob|3|bob|nice one, mike|some text
2|joe|joe likes bob|some text|2|new|42|time1|bob|1|bob|nice one, joe|some text
2|joe|joe likes bob|some text|2|new|42|time1|bob|2|bob|double nice one, me|some text
2|joe|joe likes bob|some text|2|new|42|time1|bob|2|bob|nice one, me|some text
2|joe|joe likes bob|some text|2|new|42|time1|bob|3|bob|nice one, mike|some text

OK, now you can see the problem, let's see why it's happening. Is each of these rows supposed to be there? In other words, should you see a 1|old if at least one of the first three combinations are there?

If not, which ones shouldn't be causing it? You need to filter something out in either the WHERE or the JOIN.

If so, then you need a GROUP BY to merge together the relevant fields, or an OR somewhere, more likely the first.

Step through all of the groups asking the same question. If you get to the point where you need a GROUP BY on the columns you're actually displaying, it's simpler to just use a SELECT DISTINCT.

You also might want to step back and ask whether you really want a full JOIN of long_summary with summary with long_summary. That's 8*3*8=192 rows that you've filtered down to 21. Does that make sense, or did you only expect, say, 24 rows to filter down? If the latter, you've got the JOIN wrong. Either one of those JOINs shouldn't be there at all, or it should be a one-to-one instead of one-to-many JOIN, or something else is wrong with it.

By the way, you might be able to tell from my test above that I used sqlite3 rather than mysql, just because it's a lot simpler to get and running. I doubt that makes any difference, but if you test in mysql and see different results, by all means let me know.

于 2013-01-04T06:56:22.437 回答