Получите несколько результатов GROUP BY на группу или используйте отдельную составную таблицу - PullRequest
0 голосов
/ 02 марта 2010

Я работаю над веб-приложением аукциона. Теперь у меня есть таблица с предложениями, и из этой таблицы я хочу выбрать последние 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), и просто использовать ее в соединении. Таким образом, я могу просто присоединиться к аукциону и получить последний результат.

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

  • вставить ставку в ставки, получить lastinserteid
  • получить строку bids_history для этого аукционный продукт
    • взорвать строку
    • вставить новые значения
    • проверить, если их больше 3
    • взорвать массив и снова вставить строку

Все это кажется мне не очень хорошим решением. Я действительно не знаю, куда идти. Пожалуйста, имейте в виду, что это веб-сайт с большим количеством предложений, они могут получить до 15.000 предложений на аукцион. Может быть, из-за этой суммы группировка и заказ не очень хороший путь. Пожалуйста, поправьте меня, если я ошибаюсь.

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

Может кто-нибудь помочь мне решить эту проблему!

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

EDIT

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

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

Ответы [ 5 ]

1 голос
/ 03 марта 2010

Используя пользовательскую переменную и поток управления , в итоге я получаю это (просто замените <=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
0 голосов
/ 02 марта 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

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

0 голосов
/ 02 марта 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.

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

0 голосов
/ 02 марта 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 пусто, но я думаю, что это должно работать.

0 голосов
/ 02 марта 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), чтобы это работало быстро.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...