Получите несколько результатов GROUP BY для каждой группы или используйте отдельную объединенную таблицу.

Я работаю над веб-приложением аукциона. Теперь у меня есть таблица со ставками, и из этой таблицы я хочу выбрать последние 10 ставок на аукцион.

Теперь я знаю, что могу получить последнюю ставку, используя что-то вроде:

SELECT bids.id FROM bids WHERE * GROUP BY bids.id ORDER BY bids.created

Теперь я прочитал, что установить количество для результатов GROUP BY не так просто, на самом деле я не нашел простого решения, если оно есть, я хотел бы это услышать.

Но я придумал несколько решений для решения этой проблемы, но я не уверен, что делаю это хорошо.

Альтернатива

Первым делом нужно создать новую таблицу, назвав ее bids_history. В этой таблице я храню строку последних элементов.

пример:

bids_history
================================================================
auction_id   bid_id     bidders               times
    1        20,25,40   user1,user2,user1     time1,time2,time3

Мне также нужно хранить имена и время, потому что я не нашел простого способа взять строку, используемую в bid_id(20,25,40), и просто использовать ее в соединении. Таким образом, я могу просто присоединиться к идентификатору аукциона, и у меня будет последний результат.

Теперь, когда будет размещена новая ставка, выполните следующие действия:

  • вставить ставку в ставки получить последнийinserteid
  • get the bids_history string for this auction product
    • explode the string
    • вставить новые значения
    • проверить, если их больше 3
    • взорвать массив и снова вставить строку

Все это кажется мне не очень удачным решением. Я действительно не знаю, куда идти. Пожалуйста, имейте в виду, что это веб-сайт с большим количеством торгов, они могут доходить до 15 000 ставок на аукционный лот. Может быть, из-за этой суммы ГРУППИРОВКА и ЗАКАЗ не лучший способ. Пожалуйста, поправьте меня, если я ошибаюсь.

После окончания аукциона я очищаю таблицу ставок, удаляю все ставки и сохраняю их в отдельной таблице.

Может кто-нибудь, пожалуйста, помогите мне решить эту проблему!

И если вы были, спасибо за чтение ..

РЕДАКТИРОВАТЬ

Таблицы, которые я использую:

bids
======================
id      (prim_key)
aid     (auction id)
uid     (user id)
cbid    (current bid)
created (time created)
======================

auction_products
====================
id        (prim_key)
pid       (product id)
closetime (time the auction closses)

Что я хочу в результате запроса:

result
===============================================
auction_products.id   bids.uid   bids.created
2                        6         time1
2                        8         time2
2                        10        time3
5                        3         time1
5                        4         time2
5                        9         time3
7                        3         time1
7                        2         time2
7                        1         time3

Итак, это последние ставки на аукционе, на выбор по номеру, 3 или 10.


person Saif Bechan    schedule 02.03.2010    source источник
comment
Вышлю всю структуру, может будет понятнее   -  person Saif Bechan    schedule 03.03.2010


Ответы (5)


Используя пользовательскую переменную и поток управления, я получаю следующее (просто замените <=3 на <=10, если вам нужны десять аукционов):

SELECT a.*
FROM
 (SELECT aid, uid, created FROM bids ORDER BY aid, created DESC) a,
 (SELECT @prev:=-1, @count:=1) b
WHERE
 CASE WHEN @prev<>a.aid THEN
   CASE WHEN @prev:=a.aid THEN
    @count:=1
   END
 ELSE
   @count:=@count+1
 END <= 3
person Patrick    schedule 03.03.2010
comment
Гений! Это работает просто отлично. Это работает немного медленнее, чем моя старая версия с использованием объединенной таблицы. Я сделаю еще несколько тестов, а затем сделаю выбор. Я думаю, что это самое элегантное решение проблемы, и думаю, что это работает быстрее, чем использование подзапроса. - person Saif Bechan; 03.03.2010

Зачем делать это в одном запросе?

$sql = "SELECT id FROM auctions ORDER BY created DESC LIMIT 10";
$auctions = array();

while($row = mysql_fetch_assoc(mysql_query($sql)))
  $auctions[] = $row['id'];

$auctions = implode(', ', $auctions);
$sql = "SELECT id FROM bids WHERE auction_id IN ($auctions) ORDER BY created LIMIT 10";
// ...

Очевидно, вы должны обрабатывать случай, когда, например. $auctions пусто, но я думаю, что это должно работать.

person Aistina    schedule 02.03.2010
comment
Я действительно не хочу использовать цикл для этого. Я просто хочу получить его как полный набор результатов. - person Saif Bechan; 03.03.2010

РЕДАКТИРОВАТЬ: Это неправильно :-)

Вам нужно будет использовать подзапрос:

SELECT bids1.id
FROM ( SELECT *
       FROM bids AS bids1 LEFT JOIN
            bids AS bids2 ON bids1.created < bids2.created
                          AND bids1.AuctionId = bids2.AuctionId
       WHERE bid2.id IS NULL)
ORDER BY bids.created DESC
LIMIT 10

Таким образом, подзапрос выполняет левое соединение от ставок к самому себе, сопоставляя каждую запись со всеми записями, которые имеют одинаковый аукционный идентификатор и дату создания, которая позже его собственной даты создания. Для самой последней записи не будет другой записи с большей датой создания, поэтому эта запись не будет включена в объединение, но, поскольку мы используем левое соединение, она будет включена, а все поля bids2 будут нулевыми. , следовательно, оператор WHERE bid2.id IS NULL.

Таким образом, подзапрос имеет одну строку для каждого аукциона, содержащую данные самой последней ставки. Затем просто выберите первую десятку, используя orderby и limit.

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

person adharris    schedule 02.03.2010
comment
э-э-э, хватка, которая этого не сделает, дай мне подумать еще - person adharris; 02.03.2010

Хорошо, это должно работать:

SELECT bids1.id
FROM bids AS bids1 LEFT JOIN
     bids AS bids2 ON bids1.created < bids2.created
                   AND bids1.AuctionId = bids2.AuctionId
GROUP BY bids1.auctionId, bids1.created
HAVING COUNT(bids2.created) < 9

Так что, как и раньше, мы оставили ставки объединения отдельно друг от друга, чтобы мы могли сравнить каждую ставку со всеми остальными. Затем сгруппируйте его сначала по аукциону (нам нужны последние десять ставок на аукционе), а затем по созданному. Поскольку левое соединение связывает каждую ставку со всеми предыдущими ставками, мы можем подсчитать количество ставок2.созданных для каждой группы, что даст нам количество ставок, сделанных до этой ставки. Если этот счетчик равен ‹ 9 (поскольку у первого будет count == 0, он нулевой индекс), это одна из десяти самых последних ставок, и мы хотим выбрать ее.

person adharris    schedule 02.03.2010

Чтобы выбрать последние 10 ставки для данного аукциона, просто создайте нормализованную bids таблицу (1 запись на ставку) и выполните следующий запрос:

SELECT  bids.id
FROM    bids
WHERE   auction = ?
ORDER BY
        bids.created DESC
LIMIT 10

Чтобы выбрать последние 10 ставок для нескольких аукционов, используйте это:

SELECT  bo.*
FROM    (
        SELECT  a.id,
                COALESCE(
                (
                SELECT  bi.created
                FROM    bids bi
                WHERE   bi.auction = a.id
                ORDER BY
                        bi.auction DESC, bi.created DESC, bi.id DESC
                LIMIT 1 OFFSET 9
                ), '01.01.1900'
                ) AS mcreated
                COALESCE(
                (
                SELECT  bi.id
                FROM    bids bi
                WHERE   bi.auction = a.id
                ORDER BY
                        bi.auction DESC, bi.created DESC, bi.id DESC
                LIMIT 1 OFFSET 9
                ), 0)
                AS mid
        FROM    auctions a
        ) q
JOIN    bids bo
ON      bo.auction >= q.auction
        AND bo.auction <= q.auction
        AND (bo.created, bo.id) >= (q.mcreated, q.mid)

Создайте составной индекс для bids (auction, created, id), чтобы это работало быстро.

person Quassnoi    schedule 02.03.2010
comment
Когда я использую этот метод, я получаю «Подзапрос возвращает более 1 строки» - person Saif Bechan; 03.03.2010
comment
Спасибо за все ответы, но у меня проблемы. Столбец q.auction не существует. Я изменил его на q.mid, но этот запрос не дал результатов. - person Saif Bechan; 03.03.2010
comment
@Saif: как вы связываете ставку с продуктом? - person Quassnoi; 03.03.2010