2010-01-06 99 views
5

我的平臺:PHP和MySQL:重複輸入的問題 - 需要每個條目顯示只有一次,但他們重複

PHP & MySQL的

我在這裏:

我有4個表格,即'書籍','book_type','book_categories','all_categories'。

我所試圖做的事:

在簡單的話,我想從所有表顯示所有在股票即IN_STOCK =「Y」的書籍,所有的書相關的信息,只有一次不重複條目。目前,每本書都重複出版,我只想向他們展示一次。

當前的問題:

在我的應用程序內的前端,這些條目都一再表明,當在的時候,我希望他們出現一次(如DISTINCT/UNIQUE),而不是重複的事實他們自己。

我的懷疑:

我懷疑是重複數據是因爲每個本本屬於類別。每個書籍條目都顯示多次,因爲它屬於一個類別。混亂?我的意思是,如果book1屬於4個類別,則book1會顯示4次。如果book2屬於2類,則顯示2次。

我需要什麼:

我需要& PHP MySQL代碼,將解決上述問題。我希望我們可以在不使用mySQL中的GROUP_CONCAT的情況下解決問題,因爲同樣的限制(1024?)。一本書可以屬於許多類別,我不想冒着使用GROUP_CONCAT丟失任何數據的風險。我也想在單個查詢中執行此操作,而不必在循環中重複訪問數據庫。感謝您的理解。是

所有的表和相應的數據複製的問題如下:

CREATE TABLE IF NOT EXISTS `books` (
    `book_id` int(11) NOT NULL auto_increment, 
    `book_type_id` int(11) NOT NULL, 
    `book_title` varchar(50) NOT NULL, 
    `book_price` smallint(4) NOT NULL, 
    `in_stock` char(1) NOT NULL, 
    PRIMARY KEY (`book_id`), 
    KEY `book_type_id` (`book_type_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

-- 
-- Dumping data for table `books` 
-- 

INSERT INTO `books` (`book_id`, `book_type_id`, `book_title`, `book_price`, `in_stock`) VALUES 
(1, 1, 'My Book 1', 10, 'y'), 
(2, 1, 'My Book 2', 20, 'n'), 
(3, 2, 'My Book 3', 30, 'y'), 
(4, 3, 'My Book 4', 40, 'y'), 
(5, 2, 'My Book 5', 50, 'n'), 
(6, 1, 'My Book 6', 60, 'y'), 
(7, 3, 'My Book 7', 70, 'n'), 
(8, 2, 'My Book 8', 80, 'n'), 
(9, 1, 'My Book 9', 90, 'y'), 
(10, 3, 'My Book 10', 100, 'n'); 

-- 
-- Table structure for table `book_type` 
-- 

CREATE TABLE IF NOT EXISTS `book_type` (
    `book_type_id` int(11) NOT NULL auto_increment, 
    `book_type` varchar(50) NOT NULL, 
    PRIMARY KEY (`book_type_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

-- 
-- Dumping data for table `book_type` 
-- 

INSERT INTO `book_type` (`book_type_id`, `book_type`) VALUES 
(1, 'Good'), 
(2, 'Better'), 
(3, 'Best'); 


-- 
-- Table structure for table `book_categories` 
-- 

CREATE TABLE IF NOT EXISTS `book_categories` (
    `book_id` int(11) NOT NULL, 
    `cat_id` int(11) NOT NULL, 
    PRIMARY KEY (`book_id`,`cat_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- 
-- Dumping data for table `book_categories` 
-- 

INSERT INTO `book_categories` (`book_id`, `cat_id`) VALUES 
(1, 1), 
(1, 2), 
(1, 3), 
(1, 4), 
(1, 5), 
(2, 1), 
(2, 2), 
(3, 1), 
(3, 2), 
(3, 3); 


-- 
-- Table structure for table `all_categories` 
-- 

CREATE TABLE IF NOT EXISTS `all_categories` (
    `cat_id` int(11) NOT NULL auto_increment, 
    `category` varchar(50) NOT NULL, 
    PRIMARY KEY (`cat_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

-- 
-- Dumping data for table `all_categories` 
-- 

INSERT INTO `all_categories` (`cat_id`, `category`) VALUES 
(1, 'Comedy'), 
(2, 'Drama'), 
(3, 'Romance'), 
(4, 'Horror'), 
(5, 'Trivia'), 
(6, 'Puzzles'), 
(7, 'Riddles'), 
(8, 'Kids'), 
(9, 'Gents'), 
(10, 'Ladies'); 

我的目標:

//MY QUERY: 
SELECT books.book_title, books.book_price, 
     book_type.book_type, 
     all_categories.category 
FROM books 
LEFT JOIN book_type  ON books.book_type_id = book_type.book_type_id 
LEFT JOIN book_categories ON books.book_id = book_categories.book_id 
LEFT JOIN all_categories ON book_categories.cat_id = all_categories.cat_id 
WHERE books.in_stock = 'y' 

電流輸出:

book_title book_price book_type  category 
My Book 1 10   Good   Comedy 
My Book 1 10   Good   Drama 
My Book 1 10   Good   Romance 
My Book 1 10   Good   Horror 
My Book 1 10   Good   Trivia 
My Book 3 30   Better   Comedy 
My Book 3 30   Better   Drama 
My Book 3 30   Better   Romance 
My Book 4 40   Best   NULL 
My Book 6 60   Good   NULL 
My Book 9 90   Good   NULL 

需要下面的輸出:

book_title book_price book_type  category 
My Book 1 10   Good   Comedy, Drama, Romance, Horror, Trivia 
My Book 3 30   Better   Comedy, Drama, Romance 
My Book 4 40   Best   NULL 
My Book 6 60   Good   NULL 
My Book 9 90   Good   NULL 

感謝所有提前。

+0

請注意我對您的100條查詢語句的編輯。 – MindStalker 2010-01-06 20:14:21

+0

SELECT book.book_id,all_categories.category FROM book_category JOIN all_categories on book_categories.cat_id = all_categories.cat_id JOIN book on books.book_id = book_categories.book_id WHERE books.in_stock ='y'; – MindStalker 2010-01-07 14:22:03

+0

OR SELECT book_categories.book_id,all_categories.category FROM book_category JOIN all_categories on book_categories.cat_id = all_categories.cat_id WHERE book_id IN(SELECT book_id FROM books WHERE books.in_stock ='y'); – MindStalker 2010-01-07 14:22:46

回答

3

的最佳方式。查詢表seperately和PHP加入他們的行列,可能使你的查詢看起來像這樣

book_id book_title book_price book_type   
    1 My Book 1 10   Good   
    2 My Book 3 30   Better   
    3 My Book 4 40   Best   
    4 My Book 6 60   Good    
    5 My Book 9 90   Good   

    book_id, category 
    1 Comedy 
    1 Drama 
    1 Romance 
    2 Comedy 

編輯:

不,你不應該需要對DB 100次命中,只有兩個,一個拿到書,另一個拿到分類。循環將在PHP中完成以循環遍歷第二個查詢並將數據與第一個查詢結合起來。第二個查詢可能是

SELECT book.book_id,all_categories.category FROM book_category JOIN all_categories on book_categories.cat_id = all_categories.cat_id JOIN books books.book_id = book_categories.book_id WHERE books.in_stock ='y';

OR

SELECT book_categories.book_id, all_categories.category FROM book_category 
JOIN all_categories on book_categories.cat_id=all_categories.cat_id 
WHERE book_id IN (SELECT book_id FROM books WHERE books.in_stock= 'y'); 
+0

感謝您的迴應。這意味着除了獲取我的數據的查詢之外,它是一個額外的循環,爲每個數據提取類別。這意味着如果我有100本庫存的書,那麼只是爲了獲得這些類別,這對數據庫來說是額外的100個點擊(1次點擊/查詢/預訂)。我覺得來自很多用戶的很多點擊會嚴重取消網站。那有意義嗎?請讓我知道你對此的看法。 – Devner 2010-01-06 19:04:14

+0

讓它現在工作,稍後優化 – 2010-01-06 19:16:53

+0

@ d03boy好吧,現在我該如何優化它?謝謝。 – Devner 2010-01-06 19:31:43

1

好友,你應該看看MySQL的功能GROUP_CONCAT()http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

這將是東西線之間:確保你不會丟失任何數據將多個查詢

SELECT stuff, GROUP_CONCAT(DISTINCT category ORDER BY category DESC SEPARATOR ', ') 
GROUP BY category, price, book_type 
+0

嗨碰撞。 GROUP_CONCAT只允許最多1024個字節。這意味着如果(類別+分隔符)長度大於1024字節,則查詢將失敗。我不正確嗎?正如我所提到的,一本書可以屬於很多類別。平均而言,該類別的長度爲15個字節。現在,如果該書屬於100個類別,則佔用的空間爲1500字節,超過1024個字節,這會導致結果不正確。我知道GROUP_CONCAT,並且出於同樣的原因想避免它。請讓我知道你的想法。謝謝。 – Devner 2010-01-06 19:09:17

+0

有設置'group_concat_max_len'(默認1024),也許你可以設置更高? – Clash 2010-01-06 21:00:02

+0

嗨衝突,我不太確定這是否可以通過腳本完成。我認爲這可能涉及網絡託管人員(據我所知)不願意改變任何事情。大多數時候,我的同事報告說,服務器設置的任何更改都會經常被拒絕,因爲Web主機傾向於通過根據用戶需求更改設置來避免濫用。所以我想在沒有得到他們的支持的情況下解決它。我認爲,如果我們能夠得到一個完美的解決方案,那麼我們不必再擔心託管人員,就類似的問題而言。希望這是有道理的。 – Devner 2010-01-06 22:07:23

1

您也可以使用CONCAT_WS分隔符使用子查詢,像這樣:

SELECT books.book_title, 
    books.book_price, 
    book_type.book_type, 
    CONCAT_WS(', ', ( 
         SELECT all_categories.category 
          FROM all_categories 
         WHERE all_categories.cat_id = book_categories.cat_id 
        ) 
      ) AS book_category_list 
FROM books 
LEFT JOIN book_type 
     ON books.book_type_id = book_type.book_type_id     
LEFT JOIN book_categories 
     ON books.book_id = book_categories.book_id 
    WHERE books.in_stock = 'y' 

對不起,格式化了有點古怪那裏。

+0

嗨Skone。你有沒有機會嘗試你的查詢?我做了,它仍然給我與CURRENT OUTPUT相同的結果,除了查詢結果不顯示NULL值。它仍然重複我想避免的行。 CONCAT_WS的限制是什麼? GROUP_CONCAT的限制是1024字節,所以你有關於CONCAT_WS限制的想法嗎?請告訴我。謝謝。 – Devner 2010-01-06 19:14:51

+0

我沒有真的嘗試它 - 抱歉,它沒有按預期工作。 我現在有點忙,但我會嘗試在今晚晚些時候回答一個答案(沒有承諾):P 乾杯。 – Skone 2010-01-06 23:03:44

+0

謝謝並感謝您的努力。 – Devner 2010-01-07 04:18:51

1

很簡單。通過添加組。所以它會是這樣的:

編輯:它看起來像這樣做的最好方法是使用組concat(即使你擔心它的上限),以避開上限它有我會建議在運行時更新它。所以它會是這樣的:

SET GLOBAL group_concat_max_len = SOME_BIG_VALUE; #SOME_BIG_VALUE >> 1024 

SELECT books.book_title, books.book_price, 
     book_type.book_type, 
     GROUP_CONCAT(all_categories.category) 
FROM books 
LEFT JOIN book_type  ON books.book_type_id = book_type.book_type_id 
LEFT JOIN book_categories ON books.book_id = book_categories.book_id 
LEFT JOIN all_categories ON book_categories.cat_id = all_categories.cat_id 
WHERE books.in_stock = 'y' 
GROUP BY books.book_title 
+0

嗨,您提供的查詢僅提取書名「My Book 1」和「My Book 3」的第一個類別。對於其餘書籍(My Book 4,6和9),該類別爲NULL。簡而言之,雖然行已停止重複,但所有類別均未檢索到。只有第一類是。如果您可以修改您的查詢以便顯示所有類別,我相信這可以解決問題。謝謝。 – Devner 2010-01-06 21:18:28

+0

對不起,我編輯之前,我閱讀你的意見必須通過託管公司。 – 2010-01-07 18:23:20

+0

+1擴展GROUP_CONCAT代碼 – Devner 2010-01-08 07:51:03

0

您是否嘗試添加一個獨特的選擇?

SELECT DISTINCT books.book_title, books.book_price, 
    book_type.book_type, 
    all_categories.category 
FROM books 
LEFT JOIN book_type  ON books.book_type_id = book_type.book_type_id 
LEFT JOIN book_categories ON books.book_id = book_categories.book_id 
LEFT JOIN all_categories ON book_categories.cat_id = all_categories.cat_id 
WHERE books.in_stock = 'y' 
GROUP BY books.book_title 
+0

感謝您的評論,吉姆。查詢結果與WillMatt提供的查詢結果相同。請參閱我對他的回答的評論。再次感謝。 – Devner 2010-01-06 21:21:11

1

設置會議變量爲較大的值,運行與GROUP_CONCAT您的查詢,然後重置回全球值。

SET SESSION [email protected]@max_allowed_packet; 

SELECT books.book_title, books.book_price, 
     book_type.book_type, 
     GROUP_CONCAT(all_categories.category) 
FROM books 
LEFT JOIN book_type  ON books.book_type_id = book_type.book_type_id 
LEFT JOIN book_categories ON books.book_id = book_categories.book_id 
LEFT JOIN all_categories ON book_categories.cat_id = all_categories.cat_id 
WHERE books.in_stock = 'y' 
GROUP BY books.book_id; 

SET SESSION [email protected]@group_concat_max_len; 
+0

+1。謝謝。 – Devner 2010-01-08 07:53:11