2010-07-27 4 views
15

Возьмите случай с двумя таблицами: tbl_product и tbl_transaction.
tbl_product списков деталей продуктов, включая имена и идентификаторы в то время как tbl_transaction списки сделок с участием продуктов и включает в себя дату, продукт-идентификаторы, клиент и т.д.Как ограничить результаты LEFT JOIN

мне нужно отобразить веб-страницу, показывающую 10 продуктов и для каждого продукта, последних 5 транзакций. До сих пор нет запроса LEFT JOIN, и подзапрос ниже работал бы, если бы mysql мог разрешить часть tx.product_id=ta.product_id (с ошибкой Неизвестный столбец «ta.product_id» в «where clause»: [ERROR: 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 

Конечно, это незаконно, но я действительно хочу это не было!

+0

У вас нет предложения «ON» для вашего присоединения? –

+0

Даже с предложением ON он по-прежнему извлекает более 5 транзакций. Если я удалю 'tx.product_id = ta.product_id' и изменю на' LEFT JOIN (* my limit sql *) tb ON tb.product_id = ta.product_id', все еще не то, что я хочу ~ –

+0

Имеет ли ваша таблица транзакций 'tbl_transaction 'есть идентификатор? – gnarf

ответ

6

Здесь функции ранжирования будут очень полезны. К сожалению, 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 
+0

Спасибо за ответ, Томас. Да, 'tbl_transaction' имеет в качестве первичного ключа столбец AUTO_INCREMENT. Я попробовал ваше предложение (хотя я не совсем понял его полностью), и я получил список продуктов, но ** без каких-либо ** транзакций. Почему самосоединение (на tbl_transaction [tx> -

+0

@eddy edu - Суть его в том, чтобы наложить рейтинг на транзакции по продукту. С этой целью я сравниваю таблицу транзакций с самим собой, чтобы найти количество транзакций для данного продукта раньше, чем данная строка. Самая ранняя строка для продукта должна содержать отсчет нуля. Теперь, если вы получаете нечетные результаты, у меня есть пара вопросов. Во-первых, может ли дата транзакции иметь значение NULL? Во-вторых, можно ли дублировать дату транзакции (две строки для одного и того же product_id и даты)? – Thomas

+1

transaction_date не может быть NULL. transaction_date можно дублировать (один продукт может иметь несколько транзакций за определенную дату). Мне нужно оценивать транзакции по продукту (чтобы я мог «группировать» свои транзакции по продуктам), мне просто нужно посмотреть, как входит столбец даты. –

-2

Вам нужно вытащить условие соединения из вашего подзапроса. Попробуйте:

SELECT 
    ta.product_id, 
    ta.product_name, 
    tb.transaction_date 
FROM tbl_product ta 
LEFT JOIN (SELECT tx.transaction_date 
      FROM tbl_transaction tx 
      ORDER BY tx.transaction_date DESC 
      LIMIT 5) tb 
ON ta.product_id=tb.product_id 
LIMIT 10 
+1

Этот работает, но только ОГРАНИЧИВАЕТ первый продукт. –

+2

Это не работает, потому что ваш подзапрос возвращает только последние 5 транзакций по всем транзакциям. Он заявил «за каждый продукт, за последние 5 транзакций». – nategood

1

Это терпит неудачу, потому что когда вы поставите скобки вокруг вашего запроса и дать ему псевдоним «Тб» вы создали производную таблицу. Ваша производная таблица не имеет никакого знания tbl_product таблицы, имеющей псевдоним «та»

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

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 

Вы могли бы и нас " в»и укажите 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

После изменения (удаление ссылки tbl_product в подзапросе и добавление ее в предложение ON) запрос работает нормально, но LIMIT, похоже, применим только к первому продукту, т.е. я получаю список из 10 продуктов, первый из которых имеет 5 но у всех остальных нет. –

+0

Опять же ответ потому, что если ваша производная таблица. «LIMIT» в производной таблице не имеет отношения к «LIMIT» во всем запросе. Как насчет некоторых данных образца? – Matthew

+0

Отредактировал мой ответ, чтобы лучше объяснить – Matthew

0

Edit:

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

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

+0

Это ошибка с загадочной ошибкой, которая фиксируется только с помощью предложения ON. А после «исправить» набор результатов содержит только первый продукт с 5 транзакциями - другие продукты игнорируются. –

+0

Я считал это, но я уверен, что есть одно-запросное решение! Должно быть! –