從聯接表獲取一行

[英]Fetching a Single Row from Join Table


Here are my tables:

這是我的表:

CREATE TABLE `articles` (
    `id` int(10) unsigned not null auto_increment,
    `author_id` int(10) unsigned not null,
    `date_created` datetime not null,
    PRIMARY KEY(id)
) ENGINE=InnoDB;

CREATE TABLE `article_contents` (
    `article_id` int(10) unsigned not null,
    `title` varchar(100) not null,
    `content` text not null,
    PRIMARY KEY(article_id)
) ENGINE=InnoDB;

CREATE TABLE `article_images` (
    `article_id` int(10) unsigned not null,
    `filename` varchar(100) not null,
    `date_added` datetime not null,
    UNIQUE INDEX(article_id, filename)
) ENGINE=InnoDB;

Every article can have one or more images associated with it. I'd like to display the last 40 written articles on a page, along with the most recent image associated with the article. What I can't figure out is how to join with the article_images table, and only retrieve a single row.

每一篇文章都可以有一個或多個與之相關的圖片。我想在一個頁面上顯示最近的40篇文章,以及與文章相關的最新圖片。我搞不懂的是如何與article_images表連接,只檢索一行。

Edit: It's important that the solution performs well. The solutions I've seen so far -- which use derived tables -- take a minute or more to complete.

編輯:重要的是解決方案要表現良好。到目前為止我所看到的解決方案——使用派生表——需要一分鍾或更長的時間來完成。

11 个解决方案

#1


22  

After looking over the other answers, it helped me realize an underlying problem.

在看完其他的答案后,它幫助我意識到一個潛在的問題。

The articles table and article_images table both need to have an additional index.

articles表和article_images表都需要有一個附加索引。

This is what you have now:

這就是你現在擁有的:

CREATE TABLE `articles` (
    `id` int(10) unsigned not null auto_increment,
    `author_id` int(10) unsigned not null,
    `date_created` datetime not null,
    PRIMARY KEY(id)
) ENGINE=InnoDB;

CREATE TABLE `article_images` (
    `article_id` int(10) unsigned not null,
    `filename` varchar(100) not null,
    `date_added` datetime not null,
    UNIQUE INDEX(article_id, filename)
) ENGINE=InnoDB;

This is what you need:

這就是你所需要的:

CREATE TABLE `articles` (
    `id` int(10) unsigned not null auto_increment,
    `author_id` int(10) unsigned not null,
    `date_created` datetime not null,
    PRIMARY KEY(id),
    INDEX (date_created DESC)
) ENGINE=InnoDB;

CREATE TABLE `article_images` (
    `article_id` int(10) unsigned not null,
    `filename` varchar(100) not null,
    `date_added` datetime not null,
    UNIQUE INDEX (article_id, filename),
    INDEX (article_id, date_added),
) ENGINE=InnoDB;

articles
The new index for ordering the articles by insertion date in descending order

冠詞按插入日期降序排列冠詞的新索引

article_images
The first index is still needed since it will guard against attaching the another image with the same filename to an article.
The second index will make finding the most recent image simple,

article_images仍然需要第一個索引,因為它將防止將具有相同文件名的另一個映像附加到文章中。第二個索引將使查找最近的圖像變得簡單,

With those new indexes in place, here is the query that will do your bidding:

有了這些新索引,下面的查詢將執行您的投標:

  SELECT
    AAA.author_id,
    AAA.date_created,
    IFNULL(BBB.title,'<NO_TITLE>') title,
    IFNULL(CCC.filename,'<NO-IMAGE>') filename
  FROM
  (
    SELECT
      AA.id,
      AA.date_added,
      BB.author_id,
      BB.date_created
    FROM
    (
      SELECT
        A.id,IFNULL(MAX(B.date_added),'1900-01-01 00:00:00') date_added
        FROM (SELECT id FROM articles ORDER BY date_created DESC LIMIT 40) A
        LEFT JOIN article_images B ON A.id = B.article_id
        GROUP BY A.id
    ) AA
    INNER JOIN articles BB USING (id)
  ) AAA
  LEFT JOIN article_contents BBB ON AAA.id=BBB.article_id
  LEFT JOIN article_images CCC
  ON (AAA.id=CCC.article_id AND AAA.date_added=CCC.date_added)
  ORDER BY AAA.date_created DESC;

The goal is first to create an internal subquery that only has 40 rows. That is what AA should bring back. Subquery AAA should have the article info plus the date the last image was inserted. The last set of joins should connect the 40 ids with a title and an image. The final step is to present the result set in descensding order.

目標是首先創建一個只有40行的內部子查詢。這就是AA應該帶回來的。子查詢AAA應該包含文章信息和最后一個圖像被插入的日期。最后一組連接應該用標題和圖像連接40個id。最后一步是按照后代順序顯示結果集。

Since I do not have sample data, I wrote three stored procedures in a sample database called stuff

由於我沒有示例數據,所以在一個名為stuff的示例數據庫中編寫了三個存儲過程

1 to make the tables

做桌子

DELIMITER $$

DROP PROCEDURE IF EXISTS `stuff`.`MakeTables` $$
CREATE PROCEDURE `stuff`.`MakeTables` ()
BEGIN

DROP TABLE IF EXISTS articles;
DROP TABLE IF EXISTS article_contents;
DROP TABLE IF EXISTS article_images;

CREATE TABLE `articles` (
    `id` int(10) unsigned not null auto_increment,
    `author_id` int(10) unsigned not null,
    `date_created` datetime not null,
    PRIMARY KEY(id),
    INDEX (date_created DESC)
) ENGINE=InnoDB;

CREATE TABLE `article_contents` (
    `article_id` int(10) unsigned not null,
    `title` varchar(100) not null,
    `content` text not null,
PRIMARY KEY(article_id)) ENGINE=InnoDB;

CREATE TABLE `article_images` (
    `article_id` int(10) unsigned not null,
    `filename` varchar(100) not null,
    `date_added` datetime not null,
    UNIQUE INDEX (article_id, filename),
    INDEX (article_id, date_added)
) ENGINE=InnoDB;

END $$

DELIMITER ;

1 to make the data

1來制作數據。

DELIMITER $$

DROP PROCEDURE IF EXISTS `stuff`.`LoadSampleData` $$
CREATE PROCEDURE `stuff`.`LoadSampleData` ()
BEGIN

    DECLARE x,y,z INT;

    SET x = 1;
    WHILE x <= 100 DO
        INSERT INTO articles (author_id,date_created) VALUES
        (RAND() * POWER(2,31),
        DATE('1970-01-01 00:00:00') + INTERVAL (RAND() * POWER(2,30)) SECOND);
        SET x = x + 1;
    END WHILE;

    SET x = 1;
    WHILE x <= 100 DO
        SET y = FLOOR(RAND() * 100);
        IF y >= 30 THEN
            INSERT INTO article_contents
            VALUES (x,
            CONCAT('TITLE_',FLOOR(RAND() * POWER(2,31))),
            CONCAT('CONTENT_',FLOOR(RAND() * POWER(2,31))));
        END IF;
        SET x = x + 1;
    END WHILE;

    SET x = 1;
    WHILE x <= 100 DO
        SELECT COUNT(1) INTO y FROM article_contents WHERE article_id = x;
        IF y = 1 THEN
            SET y = 0;
            WHILE y < 20 DO
                SET y = y + 1;
                SET z = FLOOR(RAND() * 10);
                IF z >= 5 THEN
                    INSERT INTO article_images
                    VALUES (x,
                    CONCAT('IMAGE_',FLOOR(RAND() * POWER(2,31))),
                    DATE('1970-01-01 00:00:00') + INTERVAL (RAND() * POWER(2,30)) SECOND);
                END IF;
            END WHILE;
        END IF;
        SET x = x + 1;
    END WHILE;

    SELECT COUNT(1) INTO x FROM articles;
    SELECT COUNT(1) INTO y FROM article_contents;
    SELECT COUNT(1) INTO z FROM article_images;

    SELECT CONCAT('Articles:',x,' Titles:',y,' Images: ',z) Results;

END $$

DELIMITER ;

1 to run the query

1運行查詢

DELIMITER $$

DROP PROCEDURE IF EXISTS `stuff`.`ShowLast40` $$
CREATE PROCEDURE `stuff`.`ShowLast40` ()
BEGIN

  SELECT
    AAA.author_id,
    AAA.date_created,
    IFNULL(BBB.title,'<NO_TITLE>') title,
    IFNULL(CCC.filename,'<NO-IMAGE>') filename
  FROM
  (
    SELECT
      AA.id,
      AA.date_added,
      BB.author_id,
      BB.date_created
    FROM
    (
      SELECT
        A.id,IFNULL(MAX(B.date_added),'1900-01-01 00:00:00') date_added
        FROM (SELECT id FROM articles ORDER BY date_created DESC LIMIT 40) A
        LEFT JOIN article_images B ON A.id = B.article_id
        GROUP BY A.id
    ) AA
    INNER JOIN articles BB USING (id)
  ) AAA
  LEFT JOIN article_contents BBB ON AAA.id=BBB.article_id
  LEFT JOIN article_images CCC
  ON (AAA.id=CCC.article_id AND AAA.date_added=CCC.date_added)
  ORDER BY AAA.date_created DESC;

END $$

DELIMITER ;

Here is an example output when I ran it on my Windows Desktop (MySQL 5.5.12):

下面是我在Windows桌面(MySQL 5.5.12)上運行時的輸出示例:

mysql> call maketables; call loadsampledata;
Query OK, 0 rows affected (0.31 sec)

+------------------------------------+
| Results                            |
+------------------------------------+
| Articles:100 Titles:67 Images: 666 |
+------------------------------------+
1 row in set (23.73 sec)

mysql> call showlast40;
+------------+---------------------+------------------+------------------+
| author_id  | date_created        | title            | filename         |
+------------+---------------------+------------------+------------------+
| 1576679519 | 2004-01-02 14:05:17 | TITLE_1757853515 | IMAGE_1601858163 |
|  992840519 | 2003-05-17 05:48:11 | TITLE_319026350  | IMAGE_1913708631 |
| 1366977197 | 2003-03-20 19:37:23 | <NO_TITLE>       | <NO-IMAGE>       |
| 1705517382 | 2003-02-07 16:48:56 | <NO_TITLE>       | <NO-IMAGE>       |
| 1529899841 | 2002-11-02 20:59:26 | <NO_TITLE>       | <NO-IMAGE>       |
| 1756824942 | 2002-08-28 16:01:59 | <NO_TITLE>       | <NO-IMAGE>       |
|  175825630 | 2002-05-08 13:48:56 | TITLE_240812804  | IMAGE_1214850809 |
|  757530551 | 2002-02-08 00:20:17 | TITLE_4447486    | IMAGE_1511850161 |
|  840251261 | 2002-01-25 20:06:56 | TITLE_1160842143 | IMAGE_206027488  |
|  964653347 | 2001-12-26 19:15:47 | TITLE_1552408257 | IMAGE_717719932  |
| 2106039126 | 2001-11-11 17:09:29 | <NO_TITLE>       | <NO-IMAGE>       |
| 2085991608 | 2001-08-01 12:48:20 | <NO_TITLE>       | <NO-IMAGE>       |
| 1895462094 | 2000-12-02 05:31:41 | <NO_TITLE>       | <NO-IMAGE>       |
| 1589384729 | 2000-04-28 23:55:50 | TITLE_1040850308 | IMAGE_1200414639 |
|  514341550 | 2000-04-20 07:25:05 | TITLE_188288840  | IMAGE_164856430  |
|  887359583 | 2000-02-13 03:30:47 | <NO_TITLE>       | <NO-IMAGE>       |
| 1156687499 | 1999-06-16 00:29:17 | TITLE_686398996  | IMAGE_670200418  |
| 1561242593 | 1998-12-08 05:50:17 | <NO_TITLE>       | <NO-IMAGE>       |
| 1117889993 | 1998-10-23 17:02:44 | TITLE_1491217221 | IMAGE_649630126  |
|  740063135 | 1998-09-16 23:52:41 | TITLE_579374776  | IMAGE_757313192  |
|  429699232 | 1998-04-19 01:41:17 | TITLE_73748980   | IMAGE_1881818111 |
| 1827051060 | 1998-02-27 01:01:50 | TITLE_1588619991 | IMAGE_1657322715 |
| 1442984429 | 1997-11-19 21:23:35 | TITLE_184173382  | IMAGE_597809368  |
|  152267158 | 1997-05-02 20:25:50 | <NO_TITLE>       | <NO-IMAGE>       |
| 1323598169 | 1997-03-14 16:30:38 | TITLE_1355869397 | IMAGE_1058313818 |
|   66122740 | 1997-01-05 15:12:20 | TITLE_1259073183 | IMAGE_198280936  |
|    5161474 | 1996-06-28 10:47:26 | TITLE_1876022823 | IMAGE_1138098675 |
| 1865082792 | 1996-03-01 19:09:11 | TITLE_1288151615 | IMAGE_245974646  |
| 1923481146 | 1995-08-07 00:36:11 | TITLE_922744000  | IMAGE_2067090321 |
| 1725218958 | 1995-03-18 05:15:29 | TITLE_583120586  | IMAGE_592773824  |
|  117806248 | 1995-01-05 02:34:32 | <NO_TITLE>       | <NO-IMAGE>       |
| 1428777335 | 1993-06-06 01:52:32 | TITLE_661148588  | IMAGE_633345518  |
| 1091245943 | 1993-06-05 05:51:47 | TITLE_1407444563 | IMAGE_538936256  |
| 2088382260 | 1993-03-25 06:03:29 | TITLE_1144364681 | IMAGE_1790013089 |
|  625878569 | 1992-12-21 07:41:26 | TITLE_1319355723 | IMAGE_921580624  |
|  110555110 | 1992-01-01 20:49:59 | <NO_TITLE>       | <NO-IMAGE>       |
| 1110532475 | 1991-11-20 07:19:32 | <NO_TITLE>       | <NO-IMAGE>       |
| 1726795146 | 1990-10-09 00:23:44 | TITLE_782624350  | IMAGE_1760322575 |
|  370183888 | 1990-03-30 15:59:17 | <NO_TITLE>       | <NO-IMAGE>       |
| 1497483317 | 1990-02-19 01:25:41 | TITLE_776483948  | IMAGE_665824222  |
+------------+---------------------+------------------+------------------+
40 rows in set (0.00 sec)

Give it a Try !!!

試一試!!!

UPDATE

更新

I made absolutely sure that the 40 datetimes you are reading are in fact the top 40. They are. I ran the query : select * from articles ORDER BY date_created DESC; to make sure.

我絕對肯定你讀的40個日期實際上是前40。他們是。我通過date_created DESC運行查詢:select * from articles ORDER;以確保。

UPDATE 2011-05-17 14:06

更新2011-05-17 14:06

mysql> call maketables; call loadsampledata;
Query OK, 0 rows affected (0.45 sec)

+-------------------------------------+
| Results                             |
+-------------------------------------+
| Articles:100 Titles:67 Images: 6739 |
+-------------------------------------+
1 row in set (3 min 45.45 sec)

Query OK, 0 rows affected (3 min 45.45 sec)

mysql> call showlast40;
+------------+---------------------+------------------+------------------+
| author_id  | date_created        | title            | filename         |
+------------+---------------------+------------------+------------------+
|  196582776 | 2004-01-05 14:09:04 | <NO_TITLE>       | <NO-IMAGE>       |
| 1880371016 | 2003-07-31 05:50:37 | TITLE_1191518827 | IMAGE_1562208019 |
|   22204986 | 2003-02-16 14:09:22 | <NO_TITLE>       | <NO-IMAGE>       |
|  355490160 | 2002-11-21 02:35:19 | <NO_TITLE>       | <NO-IMAGE>       |
|  869510149 | 2001-12-27 22:07:52 | TITLE_1528616779 | IMAGE_223327284  |
| 2063556512 | 2001-04-16 18:47:46 | TITLE_1839975091 | IMAGE_1282187005 |
|  529754190 | 2000-07-14 19:44:01 | TITLE_1557423205 | IMAGE_1931606737 |
|  166226262 | 1999-11-08 03:27:22 | <NO_TITLE>       | <NO-IMAGE>       |
| 1981417562 | 1999-09-11 12:59:10 | TITLE_198262896  | IMAGE_1491273871 |
|  831057001 | 1999-06-14 15:06:31 | TITLE_1170272131 | IMAGE_760396200  |
| 1454252623 | 1998-06-02 08:35:46 | <NO_TITLE>       | <NO-IMAGE>       |
| 1435450777 | 1997-11-17 18:10:34 | TITLE_482497458  | IMAGE_1331932705 |
| 1536315541 | 1997-11-02 05:24:49 | <NO_TITLE>       | <NO-IMAGE>       |
| 2078028530 | 1997-03-14 22:36:58 | TITLE_321332010  | IMAGE_1897983295 |
|  701651581 | 1997-01-13 22:36:58 | TITLE_1337390701 | IMAGE_1630983859 |
|  101442444 | 1996-11-22 09:40:16 | <NO_TITLE>       | <NO-IMAGE>       |
|   51114930 | 1996-11-20 03:24:49 | TITLE_1866751135 | IMAGE_1669595407 |
|  722056183 | 1996-08-03 15:23:01 | <NO_TITLE>       | <NO-IMAGE>       |
| 1178720989 | 1996-06-29 22:47:19 | TITLE_579734376  | IMAGE_833229222  |
|  511355958 | 1996-03-10 09:32:46 | TITLE_1540275289 | IMAGE_1168117261 |
|  831921829 | 1996-01-31 06:36:04 | TITLE_661038882  | IMAGE_1199197195 |
| 1288455163 | 1995-08-22 00:34:25 | TITLE_1599332515 | IMAGE_822445764  |
| 1976208956 | 1995-06-02 09:23:01 | TITLE_58372998   | IMAGE_793318650  |
| 2092066982 | 1995-03-28 20:35:37 | TITLE_1693142377 | IMAGE_1176935479 |
| 1083841549 | 1994-07-11 18:46:52 | TITLE_1955674591 | IMAGE_1240485919 |
|  359037132 | 1994-07-11 02:44:19 | TITLE_713454936  | IMAGE_1072569732 |
| 1471985773 | 1994-05-10 17:08:01 | TITLE_1065017724 | IMAGE_393097704  |
| 1888864730 | 1994-01-15 17:41:28 | TITLE_1060275498 | IMAGE_230810100  |
| 1688028488 | 1993-12-28 06:36:58 | <NO_TITLE>       | <NO-IMAGE>       |
| 1739777948 | 1993-02-15 00:30:31 | TITLE_1226842225 | IMAGE_1615058467 |
|  445721334 | 1991-12-15 20:54:49 | TITLE_1336145587 | IMAGE_2114729323 |
| 1661002442 | 1991-06-30 05:49:34 | TITLE_151142910  | IMAGE_1623325381 |
| 2092223006 | 1991-06-13 13:15:58 | TITLE_33175860   | IMAGE_1225117771 |
| 1553434585 | 1991-01-12 03:34:25 | TITLE_728483442  | IMAGE_1954153339 |
|  528544608 | 1990-11-10 08:21:04 | <NO_TITLE>       | <NO-IMAGE>       |
| 1043927395 | 1990-10-05 00:48:49 | TITLE_304307448  | IMAGE_1702062493 |
| 1685702960 | 1990-04-28 05:44:19 | TITLE_1909853341 | IMAGE_263553036  |
| 1392428383 | 1990-03-07 15:08:46 | <NO_TITLE>       | <NO-IMAGE>       |
|  643714153 | 1990-02-14 08:32:10 | TITLE_837416724  | IMAGE_1673964259 |
| 2132028206 | 1989-09-28 16:04:07 | TITLE_614908878  | IMAGE_1362210487 |
+------------+---------------------+------------------+------------------+
40 rows in set (0.01 sec)

Everything works as I published before even with a larger set of images. Here is the query from the ShowLast40 Stored Procedure:

所有的東西都像我之前發表的一樣,甚至還有一組更大的圖像。下面是來自ShowLast40存儲過程的查詢:

  SELECT
    AAA.author_id,
    AAA.date_created,
    IFNULL(BBB.title,'<NO_TITLE>') title,
    IFNULL(CCC.filename,'<NO-IMAGE>') filename
  FROM
  (
    SELECT
      AA.id,
      AA.date_added,
      BB.author_id,
      BB.date_created
    FROM
    (
      SELECT
        A.id,IFNULL(MAX(B.date_added),'1900-01-01 00:00:00') date_added
        FROM (SELECT id FROM articles ORDER BY date_created DESC LIMIT 40) A
        LEFT JOIN article_images B ON A.id = B.article_id
        GROUP BY A.id
    ) AA
    INNER JOIN articles BB USING (id)
  ) AAA
  LEFT JOIN article_contents BBB ON AAA.id=BBB.article_id
  LEFT JOIN article_images CCC
  ON (AAA.id=CCC.article_id AND AAA.date_added=CCC.date_added)
  ORDER BY AAA.date_created DESC;

UPDATE 2011-05-17 15:16

更新2011-05-17 3

Just for laughs, I increased the sample and reran it. Same query speed.

只是為了好玩,我增加了樣本並重新運行它。相同的查詢速度。

mysql> call maketables; call loadsampledata; call showlast40;
Query OK, 0 rows affected (0.38 sec)

+----------------------------------------+
| Results                                |
+----------------------------------------+
| Articles:1000 Titles:886 Images: 88596 |
+----------------------------------------+
1 row in set (51 min 22.29 sec)

Query OK, 0 rows affected (51 min 22.29 sec)

+------------+---------------------+------------------+------------------+
| author_id  | date_created        | title            | filename         |
+------------+---------------------+------------------+------------------+
| 1464539515 | 2004-01-07 22:45:04 | TITLE_676010724  | IMAGE_1877060293 |
|  272558724 | 2004-01-03 23:44:19 | TITLE_1213504045 | IMAGE_550812606  |
| 2000476448 | 2003-12-28 18:05:10 | TITLE_1762951489 | IMAGE_1201290847 |
|  955209697 | 2003-12-25 00:55:43 | TITLE_1064749344 | IMAGE_1335865507 |
| 1657429856 | 2003-12-19 01:03:13 | TITLE_1931852743 | IMAGE_905288424  |
|  759381001 | 2003-11-12 10:46:52 | TITLE_878255772  | IMAGE_2014780795 |
| 1269478951 | 2003-11-06 02:06:22 | TITLE_2026098781 | IMAGE_982272966  |
| 1049672131 | 2003-10-04 20:55:34 | TITLE_2043080215 | IMAGE_987859662  |
| 1429108729 | 2003-09-16 19:07:52 | TITLE_424483080  | IMAGE_35379150   |
| 1672198676 | 2003-09-13 11:49:52 | TITLE_1131552745 | IMAGE_875049630  |
| 1645878842 | 2003-08-24 13:42:04 | TITLE_1077302833 | IMAGE_702269538  |
|  172347180 | 2003-08-21 14:26:37 | TITLE_558691044  | IMAGE_1091183587 |
| 1137674509 | 2003-08-15 08:44:37 | TITLE_1982979709 | IMAGE_1234487941 |
|  282998112 | 2003-08-05 10:01:34 | TITLE_353831568  | IMAGE_738487608  |
|  246145344 | 2003-08-02 00:42:31 | TITLE_376954044  | IMAGE_1279375459 |
|  218409162 | 2003-07-14 02:55:16 | TITLE_1932540991 | IMAGE_1078689211 |
|  593263087 | 2003-07-12 22:47:01 | TITLE_1604012533 | IMAGE_834822870  |
| 2115914174 | 2003-07-06 03:06:31 | TITLE_1268165545 | IMAGE_1068632322 |
|  552557275 | 2003-07-01 16:45:22 | TITLE_2022112717 | IMAGE_1410588295 |
| 1500437041 | 2003-06-29 20:05:19 | TITLE_35559258   | IMAGE_159953586  |
| 1098371257 | 2003-06-09 07:29:37 | TITLE_1694076415 | IMAGE_1409619391 |
| 1570373503 | 2003-05-22 16:45:04 | TITLE_125157894  | IMAGE_723393492  |
| 1330507411 | 2003-05-05 21:40:07 | TITLE_1571250589 | IMAGE_701840418  |
| 1666035620 | 2003-04-26 02:51:40 | TITLE_504713706  | IMAGE_1410357553 |
| 1458179791 | 2003-04-19 05:34:25 | <NO_TITLE>       | <NO-IMAGE>       |
| 1365758305 | 2003-03-28 10:09:58 | TITLE_704554170  | IMAGE_2085080137 |
| 2131082774 | 2003-03-26 16:43:25 | TITLE_1411034929 | IMAGE_303539208  |
|  103396632 | 2003-02-14 09:11:28 | TITLE_915927396  | IMAGE_1381045723 |
|  396479202 | 2003-02-01 15:51:40 | <NO_TITLE>       | <NO-IMAGE>       |
| 2019916250 | 2003-01-30 00:44:46 | <NO_TITLE>       | <NO-IMAGE>       |
|  431091906 | 2003-01-29 13:08:37 | <NO_TITLE>       | <NO-IMAGE>       |
|  705166549 | 2003-01-23 21:37:07 | TITLE_1530318643 | IMAGE_257673696  |
| 1278327049 | 2002-12-31 16:39:40 | TITLE_772845324  | IMAGE_1355754913 |
| 1871174528 | 2002-12-30 19:03:40 | TITLE_65725764   | IMAGE_522904938  |
|  611892727 | 2002-12-22 10:19:07 | TITLE_333758274  | IMAGE_734815032  |
|  758497849 | 2002-12-04 15:05:10 | TITLE_129140574  | IMAGE_244407066  |
|  518111034 | 2002-10-17 16:38:10 | TITLE_1976498683 | IMAGE_2008599775 |
| 1737725786 | 2002-10-15 23:52:52 | TITLE_1441053871 | IMAGE_1595265847 |
| 1206055789 | 2002-10-03 22:07:52 | TITLE_562697952  | IMAGE_198940092  |
|  702790153 | 2002-08-31 17:37:16 | TITLE_1788304903 | IMAGE_1212944101 |
+------------+---------------------+------------------+------------------+
40 rows in set (0.01 sec)

Query OK, 0 rows affected (0.01 sec)

UPDATE 2011-05-17 15:40

更新2011-05-17 15:40

Here is the new output including the date of the latest image:

這是新的輸出,包括最新圖像的日期:

mysql> call showlast40;
+------------+---------------------+------------------+------------------+---------------------+
| author_id  | date_created        | title            | filename         | image_date          |
+------------+---------------------+------------------+------------------+---------------------+
| 1464539515 | 2004-01-07 22:45:04 | TITLE_676010724  | IMAGE_1877060293 | 2003-10-16 02:06:58 |
|  272558724 | 2004-01-03 23:44:19 | TITLE_1213504045 | IMAGE_550812606  | 2003-12-28 07:25:43 |
| 2000476448 | 2003-12-28 18:05:10 | TITLE_1762951489 | IMAGE_1201290847 | 2003-08-31 16:56:01 |
|  955209697 | 2003-12-25 00:55:43 | TITLE_1064749344 | IMAGE_1335865507 | 2003-11-11 18:37:07 |
| 1657429856 | 2003-12-19 01:03:13 | TITLE_1931852743 | IMAGE_905288424  | 2003-09-26 07:20:01 |
|  759381001 | 2003-11-12 10:46:52 | TITLE_878255772  | IMAGE_2014780795 | 2003-09-30 06:54:40 |
| 1269478951 | 2003-11-06 02:06:22 | TITLE_2026098781 | IMAGE_982272966  | 2003-07-28 11:59:10 |
| 1049672131 | 2003-10-04 20:55:34 | TITLE_2043080215 | IMAGE_987859662  | 2003-11-19 05:26:37 |
| 1429108729 | 2003-09-16 19:07:52 | TITLE_424483080  | IMAGE_35379150   | 2003-11-18 22:17:55 |
| 1672198676 | 2003-09-13 11:49:52 | TITLE_1131552745 | IMAGE_875049630  | 2003-06-08 00:42:58 |
| 1645878842 | 2003-08-24 13:42:04 | TITLE_1077302833 | IMAGE_702269538  | 2002-04-02 01:21:49 |
|  172347180 | 2003-08-21 14:26:37 | TITLE_558691044  | IMAGE_1091183587 | 2003-08-13 08:30:22 |
| 1137674509 | 2003-08-15 08:44:37 | TITLE_1982979709 | IMAGE_1234487941 | 2003-12-17 11:53:28 |
|  282998112 | 2003-08-05 10:01:34 | TITLE_353831568  | IMAGE_738487608  | 2003-11-08 22:03:22 |
|  246145344 | 2003-08-02 00:42:31 | TITLE_376954044  | IMAGE_1279375459 | 2003-12-05 02:30:49 |
|  218409162 | 2003-07-14 02:55:16 | TITLE_1932540991 | IMAGE_1078689211 | 2003-07-14 15:59:37 |
|  593263087 | 2003-07-12 22:47:01 | TITLE_1604012533 | IMAGE_834822870  | 2003-09-02 05:48:22 |
| 2115914174 | 2003-07-06 03:06:31 | TITLE_1268165545 | IMAGE_1068632322 | 2003-04-28 16:29:01 |
|  552557275 | 2003-07-01 16:45:22 | TITLE_2022112717 | IMAGE_1410588295 | 2003-11-01 01:55:16 |
| 1500437041 | 2003-06-29 20:05:19 | TITLE_35559258   | IMAGE_159953586  | 2003-08-02 10:34:07 |
| 1098371257 | 2003-06-09 07:29:37 | TITLE_1694076415 | IMAGE_1409619391 | 2004-01-07 01:00:13 |
| 1570373503 | 2003-05-22 16:45:04 | TITLE_125157894  | IMAGE_723393492  | 2003-09-26 23:22:43 |
| 1330507411 | 2003-05-05 21:40:07 | TITLE_1571250589 | IMAGE_701840418  | 2003-11-19 20:57:31 |
| 1666035620 | 2003-04-26 02:51:40 | TITLE_504713706  | IMAGE_1410357553 | 2003-11-18 01:30:04 |
| 1458179791 | 2003-04-19 05:34:25 | <NO_TITLE>       | <NO-IMAGE>       | <NO-IMAGE-DATE>     |
| 1365758305 | 2003-03-28 10:09:58 | TITLE_704554170  | IMAGE_2085080137 | 2003-11-11 16:35:19 |
| 2131082774 | 2003-03-26 16:43:25 | TITLE_1411034929 | IMAGE_303539208  | 2003-05-14 12:59:37 |
|  103396632 | 2003-02-14 09:11:28 | TITLE_915927396  | IMAGE_1381045723 | 2003-12-28 18:26:28 |
|  396479202 | 2003-02-01 15:51:40 | <NO_TITLE>       | <NO-IMAGE>       | <NO-IMAGE-DATE>     |
| 2019916250 | 2003-01-30 00:44:46 | <NO_TITLE>       | <NO-IMAGE>       | <NO-IMAGE-DATE>     |
|  431091906 | 2003-01-29 13:08:37 | <NO_TITLE>       | <NO-IMAGE>       | <NO-IMAGE-DATE>     |
|  705166549 | 2003-01-23 21:37:07 | TITLE_1530318643 | IMAGE_257673696  | 2003-08-23 19:06:22 |
| 1278327049 | 2002-12-31 16:39:40 | TITLE_772845324  | IMAGE_1355754913 | 2003-12-22 16:40:25 |
| 1871174528 | 2002-12-30 19:03:40 | TITLE_65725764   | IMAGE_522904938  | 2003-09-06 07:08:01 |
|  611892727 | 2002-12-22 10:19:07 | TITLE_333758274  | IMAGE_734815032  | 2003-09-22 19:16:43 |
|  758497849 | 2002-12-04 15:05:10 | TITLE_129140574  | IMAGE_244407066  | 2003-07-15 12:38:37 |
|  518111034 | 2002-10-17 16:38:10 | TITLE_1976498683 | IMAGE_2008599775 | 2004-01-06 16:37:34 |
| 1737725786 | 2002-10-15 23:52:52 | TITLE_1441053871 | IMAGE_1595265847 | 2003-11-24 15:23:10 |
| 1206055789 | 2002-10-03 22:07:52 | TITLE_562697952  | IMAGE_198940092  | 2003-08-23 11:56:46 |
|  702790153 | 2002-08-31 17:37:16 | TITLE_1788304903 | IMAGE_1212944101 | 2003-12-19 22:56:01 |
+------------+---------------------+------------------+------------------+---------------------+
40 rows in set (0.01 sec)

Here is the new query

這是新的查詢

  SELECT
    AAA.author_id,
    AAA.date_created,
    IFNULL(BBB.title,'<NO_TITLE>') title,
    IFNULL(CCC.filename,'<NO-IMAGE>') filename,
    IFNULL(CCC.date_added,'<NO-IMAGE-DATE>') image_date
  FROM
  (
    SELECT
      AA.id,
      AA.date_added,
      BB.author_id,
      BB.date_created
    FROM
    (
      SELECT
        A.id,IFNULL(MAX(B.date_added),'1900-01-01 00:00:00') date_added
        FROM (SELECT id FROM articles ORDER BY date_created DESC LIMIT 40) A
        LEFT JOIN article_images B ON A.id = B.article_id
        GROUP BY A.id
    ) AA
    INNER JOIN articles BB USING (id)
  ) AAA
  LEFT JOIN article_contents BBB ON AAA.id=BBB.article_id
  LEFT JOIN article_images CCC
  ON (AAA.id=CCC.article_id AND AAA.date_added=CCC.date_added)
  ORDER BY AAA.date_created DESC;

My query does one thing nobody else's query does:

我的查詢做了一件其他人的查詢做不到的事情:

My query gets the last 40 articles first before joining to any other table.

我的查詢在連接到任何其他表之前先獲取最后40篇文章。

Everybody else's queries joins everything first and then attempts to do LIMIT 40 on a large temp table.

其他人的查詢首先連接所有內容,然后嘗試在大型臨時表上執行LIMIT 40。

My query's running time is not a factor of the amount of data.

我的查詢的運行時間不是數據量的因數。

Regardless of the sample size I create, my query has to be the fastest !!!

不管我創建的示例大小如何,我的查詢必須是最快的!

#2


3  

This is a case where an inline subquery, rather than a join, will work well:

在這種情況下,內聯子查詢(而不是連接)將運行良好:

select articles.*,
       article_contents.title,
       article_contents.content,
       (select article_images.filename
       from article_images
       where article_images.article_id = articles.id
       order by article_images.date_added desc
       limit 1
       ) as image_filename
from articles
join article_contents
on article_contents.article_id = articles.id
order by articles.date_created desc
limit 40;

Performance wise, it will nestloop through the top 40 rows of articles, which is the fastest possible plan; and for each of these rows, the subquery will nestloop to the top applicable row in article_images, which also happens to be the fastest plan for a given article.

在性能方面,它將在文章的前40行進行循環,這是最快的計划;對於每一行,子查詢將在article_images中對最適用的行進行nestloop,這也是給定文章中最快的計划。

If you need to fetch more than a single field from the images table, I take it you've an image_id. Assuming so, grab the image_id instead, and then do a second query with an in clause to retrieve the rows you need.

如果需要從圖像表中獲取多個字段,那么我將使用image_id。假設是這樣,那么獲取image_id,然后使用in子句執行第二個查詢,以檢索所需的行。

An alternative (and slightly faster) approach will be to use triggers to keep the latest image_id stored in the articles table. Doing will allow you to left join the images directly.

另一種方法(稍微快一點)是使用觸發器將最新的image_id存儲在articles表中。這樣做可以讓你直接加入圖像。

#3


2  

Basically you want to do select rows holding group-wise maximum of a field, which was linked by ʞɔıu in MySQL - Control which row is returned by a group by.

基本上你想做選擇行控股group-wise最大的領域,由ʞ聯系ɔıu MySQL -控制哪一行返回的一組。

In MySQL it is not possible to do an ORDER BY before a GROUP BY. You can do Subselects as described in the first linked answer or as shown in MySQL Group By ordering.

在MySQL中,不可能在一個組之前完成訂單。您可以按照第一個鏈接答案中描述的方式進行子選擇,也可以按順序執行MySQL組中的操作。

In your case, this will most probably result in bad performance, so it would be possible to use two seperate queries. Not perfectly elegant, but reliable:

在您的示例中,這很可能會導致糟糕的性能,因此可以使用兩個獨立查詢。不是很優雅,但很可靠:

SELECT a.id
FROM articles a
ORDER BY a.date_created DESC
LIMIT 40

and for each of the 40 result rows with %ARTICLE_ID% being the current row id:

對於包含%ARTICLE_ID%的40個結果行中的每個行,都是當前行id:

SELECT ai.filename
FROM article_images ai
WHERE ai.article_id = %ARTICLE_ID%
ORDER BY ai.date_added DESC
LIMIT 1

My advice would be another one: redundancy. Save the latest article image redundantly in your article table. This results in easy and fast queries.

我的建議是另一個:裁員。在您的文章表中保存最新的文章圖像冗余。這會導致簡單而快速的查詢。

#4


1  

Let me First describe you the reason of time taken by the query to solve this problem. My English is not much good but I will try to explain it best way.

讓我首先向您描述查詢解決此問題所花費的時間的原因。我的英語不是很好,但我會盡力用最好的方式來解釋它。

Let's take the example of 2 table join, When we use join table command what is basically done. According to the query, engine scans the first table then it goes to second table and start reading first table and second table and where the query matches, it takes it the memory. Now Let's take the example of 3 tables join, Read 1st table then 2 second and for performing on 3rd sql, if the data is heavy then creates the tmp table and starts reading and then executing the command and if normally then stores in memory.

讓我們以兩個表連接為例,當我們使用join table命令時,基本上完成了什么。根據查詢,引擎掃描第一個表,然后轉到第二個表,開始讀取第一個表和第二個表,在查詢匹配的地方,它獲取內存。現在讓我們以3個表連接為例,讀1表,然后2秒,在第3條sql上執行,如果數據很重,那么創建tmp表並開始讀取,然后執行命令,如果正常情況下存儲在內存中。

Now your problem is not the tables joining command but the problem is structure of the 2nd table only. It has the text column and which is minimum use and during searching the engine has to pick that query and perform the read and write function on it and with every write or read the use of memory decreases and the engine become slow and slow and slow.

現在,您的問題不是表的連接命令,而是問題只是第二表的結構。它有文本列,這是最小的使用,在搜索過程中引擎必須選擇那個查詢並在它上面執行讀和寫函數,每次寫或讀,內存的使用就會減少,引擎就會變慢,變慢,變慢。

Solution: There are two solutions for this problem. First solution is to do partition of the second table horizontally and vertically. What will happen with his the engine would make the marking during search and large chunk of data would be written rapidly and the result of timing would increase. But I don't recommend the solution as it would only decease the time little but the time of reading and writing would not reduce. What would I suggest the second Solution.

解決方案:這個問題有兩個解決方案。第一個解決方案是水平和垂直地對第二個表進行分區。他的搜索引擎將會在搜索過程中做標記,大量的數據將會被快速寫入,時間的結果將會增加。但是我不推薦這個解決方案,因為它只會減少一點時間,但是閱讀和寫作的時間不會減少。第二種解決辦法是什么?

2nd Solution: Remove the text column from the 2nd table and make the 4th table of author_aritcle_content with 2 column of title and content and join the 4th table in the last. What would happen with this solution the engine first scan 1st table with 10 + 10 bytes and when we move to the second table then scanning would be done in 10 + 10 + 10 + 100 and with 3rd table it would be 10 + 10 + 10+ 100 + 10 + 100 and at this point the engine have to search only 240 bytes and your result are ready and just engine has to add contents and it would be done easily. The time reduction in the query is very large as it have not to take the text column with engine as it would join in the last, only with results which are going to be displayed.

第二種解決方案:從第二個表中刪除文本列,將author_aritcle_content的第4個表改為2列標題和內容,並在最后一個表中加入第4個表。會發生什么這個解決方案發動機第一次掃描1表10 + 10個字節,然后當我們搬到第二個表掃描將在10 + 10 + 10 + 100和第三表是10 + 10 + 10 + 100 + 10 + 100,此時發動機已經只有240字節和搜索結果都准備好了,只是引擎添加內容,這將是很容易完成的。查詢的時間減少非常大,因為它不必使用帶有engine的文本列,因為它將在最后一個中加入,只使用將顯示的結果。

Today, I added 10,000 articles in the table and executed the below query and it has taken 0.2015 secs, Each article has bytes of 65,000 and image name is 10 bytes and the query is :

今天我在表格中增加了1萬篇文章,並執行了下面的查詢,它取了0.2015秒,每篇文章的字節為65000,圖像名為10字節,查詢為:

select 
    a.id,
    a.author_id,
    a.date_created,
    b.title,
    c.filename,
    c.date_added,
    d.content
from
    articles as a,
    article_contents as b,
    article_images as c,
    article_contents as d
where
    a.id = b.article_id and
    b.article_id = c.article_id and
    c.article_id = d.article_id
order by
    a.date_created desc
limit
    0, 40;

I will again post the results with the articles numbers goes to 50,000 and time taken to execute the query.

我將再次發布結果,文章編號為50,000,執行查詢所需的時間。

#5


0  

Would something like this work?

像這樣的東西有用嗎?

select * from articles left join (select article_id, filename from article_images group by article_id order by date_added desc) on id = article_id

#6


0  

SELECT a.id, ai.filename
    FROM articles a
        LEFT JOIN (SELECT article_id, MAX(date_added) AS MaxDate
                       FROM article_images 
                       GROUP BY article_id) maxai
                INNER JOIN article_images ai
                    ON maxai.article_id = ai.article_id
                        AND maxai.MaxDate = ai.date_added
            ON a.id = maxai.article_id
    ORDER BY a.date_created DESC
    LIMIT 40

#7


0  

If performance is major concern when searching and displaying results then I propose you alter your table structure so that the last image ID is stored in the article contents table. That way retrieval speed is optimal.

如果在搜索和顯示結果時主要關注性能,那么我建議您修改表結構,使最后一個圖像ID存儲在article contents表中。這樣檢索速度是最優的。

Sacrifice insert speed for a far improved search function.

犧牲插入速度來提高搜索功能。

#8


0  

Try something like this

這樣的嘗試

SELECT  A.author_id ,
        Images.article_id ,
        Images.filename ,
        Images.date_added 
FROM    articles AS A
        LEFT JOIN ( SELECT  AI1.article_id ,
                            AI1.filename ,
                            AI1.date_added
                    FROM    article_images AS AI1
                    WHERE   AI1.date_added = ( SELECT   MAX(date_added)
                                               FROM     article_images AS AI2
                                               WHERE    AI2.article_id = AI1.article_id
                                             )
                  ) AS Images ON A.id = Images.article_id 

You will also need to add an index to the article_images table

您還需要向article_images表添加一個索引。

(article_id ASC, date_added ASC)

#9


0  

SELECT a.id,ac.title,ac.content,ai.filename

FROM articles a,article_contents ac,article_images ai

WHERE a.id=ac.article_id and a.id=ai.article_id

ORDER BY a.date_created desc

LIMIT 40 

use above query.it will works for you

使用上面的查詢。這對你有用

#10


0  

This one should be pretty efficient as it does not use any derived tables.

這個表應該非常高效,因為它不使用任何派生表。

SELECT articles.id, articles.author_id, articles.date_created,
            SUBSTRING_INDEX(GROUP_CONCAT(filename ORDER BY article_images.date_added DESC SEPARATOR "\t"),"\t",1) as latestFilename
    FROM articles
        JOIN article_images
            ON articles.id = article_images.article_id
    GROUP BY articles.id, articles.author_id, articles.date_created
    ORDER BY articles.date_created DESC
    LIMIT 40;

The GROUP_CONCAT returns a string list of all filenames in the group, ordered by article_images_date_added DESC and separated by a "\t".
The SUBSTRING_INDEX will cut the string before the first "\t" so only the latest filename will be returned.

GROUP_CONCAT返回組中所有文件名的字符串列表,由article_images_date_add DESC排序,並由“\t”分隔。SUBSTRING_INDEX將在第一個“\t”之前刪除字符串,因此只返回最新的文件名。

(Obviously, you should also have the relevant indexes added on article_images.article_id, article_images.date_created and articles.date_created.)

顯然,您還應該在article_images上添加相關索引。article_id article_images。date_created和articles.date_created)。

#11


0  

Try this if you are sure that each article has an image

如果您確定每一篇文章都有一個圖片,請嘗試一下

SELECT a.author_id,a.date_created,i.filename FROM test.articles a
left join article_images i on i.article_id=a.id
where i.date_added =(select Max(date_added) from article_images i2);

Else if is not necessary to have an image related to each article (which is more logical) this should work:

否則,如果不需要與每一篇文章相關的圖像(更符合邏輯),這應該是可行的:

SELECT a.author_id,a.date_created,i.filename FROM test.articles a
left join article_images i on (i.article_id=a.id and i.date_added =(select Max(date_added) from article_images i2))

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2011/05/12/725597ed3de9aaa18ed0dfc4a283235c.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com