ограничение последовательных значений одного столбца в SQL-запросе - PullRequest
2 голосов
/ 23 апреля 2010

У меня есть таблица со следующей структурой:

id           -int(11)
event_id     -int(11)
photo_id     -int(11)
created_at   -datetime

Как мне написать запрос, который возвратит 100 самых последних строк, но при этом гарантируется, что не будет более 4 последовательных строк с одинаковымизначение в photo_id

Ответы [ 5 ]

3 голосов
/ 23 апреля 2010

Вы можете добавить предложение where, которое отфильтровывает строки, для которых существуют 4 строки с более низким photo_id:

select *
from YourTable t1
where 4 > (
    select count(*)
    from YourTable t2
    where t1.event_id = t2.event_id
    and t1.photo_id < t2.photo_id
)
limit 100

Это может быть довольно медленным для огромных столов. Более быстрый, но очень специфичный для MySQL вариант - использовать переменные. Например:

select *
from (
    select
        @nr := case 
            when event_id = @event then @nr + 1 
            else 1 
        end as photonr
    ,   @event := event_id
    ,   t1.*
    from YourTable as t1
    cross join (select @event := -1, @nr := 1) as initvars
    order by event_id
) as subquery
where subquery.photonr < 5
limit 100;

Используемые данные испытаний:

drop table if exists YourTable;

create table YourTable (
  id int auto_increment primary key
, event_id int
, photo_id int
);

insert into YourTable (event_id, photo_id)
values (1,1), (1,2), (1,3), (1,4), (1,5), (2,1), (1,6);
0 голосов
/ 23 апреля 2010

Попробуйте это:

SELECT p.id, p.event_id, p.photo_id, p.created_at
FROM photo_table p,
    (

        SELECT photo_id, MAX(created_at) max_date
        FROM photo_table
        GROUP BY photo_id 
    ) t
WHERE p.created_at = t.max_date
        AND p.photo_id = t.photo_id
ORDER BY p.created_at DESC
LIMIT 100

Что это делает: 1. найти дату последнего изменения фотографии 2. найти только последние события каждой фотографии 3. выберите первые 100 самых последних

В PostgreSQL или Oracle было бы проще использовать аналитику / оконные функции, такие как:

FIRST (created_at) OVER (PARTITION BY photo_id ORDER BY created_at DESC)
0 голосов
/ 23 апреля 2010

Если вы используете T-SQL, проверьте http://msdn.microsoft.com/en-us/library/ms189798.aspx для функций ранжирования.

Судя по твоему вопросу, NTILE - это то, что ты хочешь. Вот моя быстрая попытка запроса, я не на терминале, поэтому он не проверен, но он должен помочь вам начать:

SELECT
  id,
  event_id,
  photo_id,
  created_at,
  NTILE(4) OVER (ORDER BY photo_id) AS 'Quartile'
FROM tbl
WHERE NTILE(4) OVER (ORDER BY photo_id)<2
ORDER BY created_at DESC

На связанной странице есть хороший пример всех функций ранжирования.

Удачи

0 голосов
/ 23 апреля 2010

в оракуле, вы бы использовали функцию задержки

LAG  (value_expression [,offset] [,default]) OVER ([query_partition_clause] order_by_clause)

не уверен, что это возможно в mySQL.

0 голосов
/ 23 апреля 2010

Я бы сказал, что что-то вроде этого поставит вас на правильный путь:

$sql = "SELECT DISTINCT * FROM myTable ORDER BY id ASC LIMIT 100";

В этом случае «DISTINCT» будет извлекать только разные строки и игнорировать повторяющиеся.

Надеюсь, это поможет.

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