Как ограничить результаты левого соединения - PullRequest
18 голосов
/ 28 июля 2010

Рассмотрим две таблицы: tbl_product и tbl_transaction.
tbl_product перечисляет сведения о продукте, включая имена и идентификаторы, тогда как tbl_transaction перечисляет транзакции, связанные с продуктами, и включает даты, идентификаторы продуктов, клиенты и т. Д.

Мне нужно отобразить веб-страницу, показывающую 10 продуктов и для каждого продукта последние 5 транзакций. До сих пор ни один запрос LEFT JOIN, похоже, не работал, и подзапрос работал бы, если бы mysql мог разрешить часть tx.product_id=ta.product_id (происходит сбой с Неизвестный столбец «ta.product_id» в «выражении where»: [ОШИБКА: 1054 ] ).

SELECT  
ta.product_id,  
ta.product_name,  
tb.transaction_date  
FROM tbl_product ta  
LEFT JOIN (SELECT tx.transaction_date FROM tbl_transaction tx WHERE tx.product_id=ta.product_id LIMIT 5) tb
LIMIT 10

Есть ли способ получить нужный листинг без использования нескольких запросов в цикле ?

Edit:
Это именно то, что мне нужно от MySQL:

SELECT ta.product_id, ta.product_name, tb.transaction_date ...  
FROM tbl_product ta  
LEFT JOIN tbl_transaction tb ON (tb.product_id=ta.product_id LIMIT 5)  
LIMIT 10

Конечно, это незаконно, но мне бы очень хотелось, чтобы этого не было!

Ответы [ 4 ]

8 голосов
/ 28 июля 2010

Здесь функции ранжирования были бы очень полезны.К сожалению, MySQL пока не поддерживает их.Вместо этого вы можете попробовать что-то вроде следующего.

Select ta.product_id, ta.product_name
    , tb.transaction_date
From tbl_product As ta
    Left Join   (
                Select tx1.product_id, tx1.transaction_id, tx1.transaction_date
                    , (Select Count(*)
                        From tbl_transaction As tx2
                        Where tx2.product_id = tx1.product_id
                            And tx2.transaction_id < tx1.transaction_id) As [Rank]
                From tbl_transaction As tx1
                ) as tb
        On tb.product_id = ta.product_id
            And tb.[rank] <= 4
Limit 10
2 голосов
/ 28 июля 2010

Сбой, потому что, когда вы ставите круглые скобки вокруг своего запроса и даете ему псевдоним "tb", вы создали производную таблицу. Ваша производная таблица не знает, что таблица tbl_product имеет псевдоним "ta"

Попробуйте использовать ON или WHERE вне производной таблицы, а затем ссылаться на эту таблицу, используя предоставленный вами псевдоним "tb"

EDIT:

Использование «LIMIT» ограничивает результаты запроса во всей его полноте. В то время как у вас есть «LIMIT 10», вы на самом деле хотите 50 строк (или меньше, если есть менее 5 исторических), верно?

10 товаров, соединенных с 5 историческими записями, возвращающими всего 50 строк.

В этом случае вы можете иметь решение для одного запроса, соединяющее таблицу продукта с самой собой в производной таблице, имеющей «LIMIT 10»

Например:

SELECT *
FROM tbl_product ta
JOIN (SELECT * FROM tbl_product tz WHERE tz.product_id = ta.product_id LIMIT 10) tc
LEFT JOIN (SELECT tx.transaction_date FROM tbl_transaction tx 
    WHERE tx.product_id=ta.product_id LIMIT 5) tb

Вы также можете использовать "in" и указать топ-10, такие как:

SELECT *
FROM tbl_product ta
LEFT JOIN (SELECT tx.transaction_date FROM tbl_transaction tx 
WHERE tx.product_id=ta.product_id LIMIT 5) tb 
WHERE ta.product_id IN 
  (SELECT z.product_id FROM tbl_product z LIMIT 10)
0 голосов
/ 12 декабря 2018

Я нашел способ сделать LEFT JOIN с подзапросом, отсортированным и ограниченным, он работает на RDS Amazon, MariaDB v10.2

LEFT JOIN activities last_activity ON last_activity.id = ( 
     SELECT id FROM activities 
     WHERE contester_id = contesters.id AND `type` IN ({$last_activity_types}) 
     ORDER BY id DESC LIMIT 1 
)

Все остальные способы сделать LEFT JOIN с GROUPING и SORTING неработает для меня.Этот пример является рабочим исключением.

0 голосов
/ 28 июля 2010

Редактировать:

Если вы хотите ввести ограничение для каждого продукта, я бы разделил его на два запроса.

Сначала получите список из 10 продуктов, а затем выполните другой запрос для каждого изте, которые возвращают последние пять транзакций.

...