Как найти диапазон дат из бд и вывести только повторяющиеся?

Тема в разделе "PHP", создана пользователем drkrol, 27 ноя 2016.

Статус темы:
Закрыта.
Модераторы: latteo
  1. drkrol

    drkrol Постоялец

    Регистр.:
    6 мар 2016
    Сообщения:
    109
    Симпатии:
    10
    Здравствуйте. Есть вот такой код.
    PHP:
    $nnomer $_POST['nnomer'];
    const 
    SQL_GET_MENU_ITEM '
    SELECT datestart, dateend FROM main WHERE namenomer = :namenomer
    '
    ;
    try{
    $pdo = new PDO("mysql:host=127.0.0.1;dbname=module;charset=utf8","root","");
    $pdo->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);

    $stmt $pdo->prepare(SQL_GET_MENU_ITEM);
    $res $stmt->execute([':namenomer' => $nnomer]);
    $row json_encode($stmt->fetchAll(PDO::FETCH_OBJ));
    echo 
    "$row";
    }catch(
    PDOException  $e ){
    exit( 
    $e->getMessage());
    }
    Бд выглядит у меня вот таким образом:
    [​IMG]
    Принцип работы скрипта: С сайта уходит ajax запрос с $_POST['nnomer']; (он равен lux), php подставляет его в pdo запрос к бд и достаёт ответ. Ответ - первая и последняя дата из диапазона дат. В моём случае ответ такой:
    Код:
    [{"datestart":"2016-11-29","dateend":"2016-12-03"},{"datestart":"2016-12-01","dateend":"2016-12-05"}]
    Всего дат 4, но по факту их будет больше.
    Так вот. Подскажите, как через php найти повторяющиеся даты? В моём случае повторяющиеся даты это: 2016-12-01, 2016-12-02 и 2016-12-03. Такое вообще возможно сделать?
     
  2. antonixus

    antonixus Постоялец

    Регистр.:
    18 июл 2016
    Сообщения:
    53
    Симпатии:
    35
    Получить повторяющиеся даты не сложно. А что потом с ними сделать? Тебе прямо в твоем скрипте это нужно сделать? Или в отдельном по всей базе?
    Самый простой вариант:

    PHP:
    //полученный массив
    $aDataFetched =  $stmt->fetchAll(PDO::FETCH_OBJ);
    //только значения
    $aDataFetchedValues array_values($aDataFetched);
    //частота встречаемости каждого значения
    $aValuesFreq array_count_values($aDataFetchedValues);
     
  3. drkrol

    drkrol Постоялец

    Регистр.:
    6 мар 2016
    Сообщения:
    109
    Симпатии:
    10
    Да. Прямо в скрипте нужно сделать пересчет и сравнить.
    Да пересчитать можно, а вот сравнить - не знаю как. Да и пересчитать я могу только тогда, как есть только 1 datestart и 1 dateend. Если больше - не знаю, как.
    PHP:
    $from = new DateTime('2016-01-30');
    $to   = new DateTime('2016-02-04');
    $period = new DatePeriod($from, new DateInterval('P1D'), $to);
    $last_date $period->getEndDate();
    $last_date_string $last_date->format('Y-m-d');
    $array_dates array_map(
        function(
    $item){return $item->format('Y-m-d');},
        
    iterator_to_array($period)
    );
    array_push($array_dates,$last_date_string);
    $date_string implode("','",$array_dates);
    $dat =  "'".$date_string."'";
    var_dump($dat)
    В конце я должен получить данные в таком виде ['2016-12-01', '2016-12-02', '2016-12-03'] . Потом я эти данные подставлю в js скрипт и он дальше будет с ними работать... Если, честно, я даже в уме не могу представить, как это работает. Прочёл уже много чего, но так и не могу понять, как такое сделать...
     
  4. nejtr0n

    nejtr0n Постоялец

    Регистр.:
    24 янв 2014
    Сообщения:
    126
    Симпатии:
    71
    Повторяющиеся даты можно получить в рамках одного атрибута. (datestart, dateend)
    group_by + count вам в помощь.
    Код:
    select * from blah group_by datestart having count(*) > 1
     
    Yulo нравится это.
  5. antonixus

    antonixus Постоялец

    Регистр.:
    18 июл 2016
    Сообщения:
    53
    Симпатии:
    35
    Блин, всё равно не могу до конца понять, что тебе нужно сделать.
    Вот у тебя есть набор дат вычисленных твоим скриптом. Есть несколько расчетов для разных диапазонов дат
    Диапазон1
    Начальная1 2016-01-30 и Конечная1 2016-02-04
    На выходе имеем заполненный диапазон '2016-01-30','2016-01-31','2016-02-01','2016-02-02','2016-02-03','2016-02-04'
    Таак, а если будет второй такой диапазон пересекающий первый:
    Диапазон2
    Начальная2 2016-02-01 и Конечная 2016-02-07
    На выходе имеем '2016-02-01','2016-02-02','2016-02-03','2016-02-04','2016-02-05','2016-02-06','2016-02-07'

    Получается, что первый и второй диапазон пересекаются следующими датами:
    '2016-02-01','2016-02-02','2016-02-03','2016-02-04'

    Эти пересекающиеся даты нужно получать?
     
  6. drkrol

    drkrol Постоялец

    Регистр.:
    6 мар 2016
    Сообщения:
    109
    Симпатии:
    10
    Да. Я вот тут вот до этого дошел. Оно, вроде, работает, но, если честно, страшно проверять)))

    PHP:
    $diaposons array_map(
        function(
    $e) { return array('datestart' => strtotime($e->datestart), 'dateend' => strtotime($e->dateend)); },
        
    json_decode('[{"datestart":"2016-11-29","dateend":"2016-12-03"},{"datestart":"2016-12-01","dateend":"2016-12-05"}]')
    );
    usort($diaposons, function($a$b) { return $a['datestart'] - $b['datestart']; });
    $result = [];
    $left $diaposons[0]['datestart'];
    $right $diaposons[0]['dateend'];
    $num count($diaposons);
    $day 24 60 60;
    for (
    $i 1$i $num; ++$i) {
        if (
    $diaposons[$i]['datestart'] > $right) {
            
    $right $diaposons[$i]['dateend'];
            continue;
        }
        
    $end min($right$diaposons[$i]['dateend']);
        
    $result[] = array(
            
    'start' => max($left $day$diaposons[$i]['datestart']),
            
    'end' => $end
        
    );
        
    $left $end;
        
    $right max($right$diaposons[$i]['dateend']);
    }
    foreach (
    $result as $r) {
        for (
    $i $r['start']; $i <= $r['end']; $i += $day) {
            echo 
    date('Y-m-d'$i), PHP_EOL;
        }
    }
    ?>
     
  7. antonixus

    antonixus Постоялец

    Регистр.:
    18 июл 2016
    Сообщения:
    53
    Симпатии:
    35
  8. 868283

    868283 Писатель

    Регистр.:
    7 май 2012
    Сообщения:
    5
    Симпатии:
    1
    смысл массив перебирать если есть group by и чтоб такого не было храните даты в формате now()
     
  9. fliuger

    fliuger Создатель

    Регистр.:
    24 янв 2017
    Сообщения:
    11
    Симпатии:
    4
    Оно?

    SELECT max(datestart), min(dateend) FROM main WHERE namenomer = :namenomer and @begdate <= dateend AND @enddate >= datestart

    на выходе имеем начало и конец пересечения периодов.

    @begdate и @enddate начало и конец интересуемого периода. если нужны просто по всем namenomer, то соответственно перед первым запросом просто берем первый подходящий период, например:

    SELECT TOP 1 @begdate =datestart, @enddate =dateend FROM main WHERE namenomer = :namenomer


    SQL синтаксис под MSSQL, для MySQL я думаю аналогию провести просто будет :)

    или вот без переменных

    SELECT max(main.datestart), min(main.dateend) FROM main, (SELECT TOP 1 datestart, dateend FROM main) as t WHERE namenomer = :namenomer and t.datestart <= main.dateend AND t.dateend >= main.datestart
     
    Последнее редактирование: 25 янв 2017
  10. Lupinuschile

    Lupinuschile Писатель

    Регистр.:
    6 фев 2017
    Сообщения:
    4
    Симпатии:
    1
    This answer is in english:

    SELECT *
    FROM database
    WHERE start_date > NOW() - INTERVAL 30 DAY
    ORDER BY start_date DESC

    Or u can use too

    select *
    from database
    where start_date between '2012-03-11 00:00:00' and '2012-05-11 23:59:00'
    order by start_date desc;
     
Статус темы:
Закрыта.