테스트 사이트 - 개발 중인 베타 버전입니다

검색 쿼리 질문입니다. 채택완료

lacomparte 7년 전 조회 3,400

A 테이블에 (징계관련 테이블)

같은 mb_id 가 여러개 insert 가 가능한데요.

운영자가 회원을 징계하면 A테이블에 해당 내용이 쌓입니다.

이때 징계 횟수를 구분짓기 위해서 

 

운영자가 a회원을 징계를 하면

1. A 테이블에 a회원의 징계 기록이 있는지 조회한다.

2. A 테이블에 a회원의 징계 기록이 있다면 insert 될 row에 stack 칼럼을 stack = stack +1 해준다.

이런 프로세스로 운영됩니다.

그래서

최초 A테이블의 자료를 보게되면

id = a | reason = 회원기만 | nick = gnu | stack = 1

id = a | reason = 광고홍보 | nick = gnu | stack = 2

이런 식으로 쌓이는데요.

 

이게 여러명이 될 경우에 검색에 조금 문제가 생겨버립니다.

id = a | reason = 회원기만 | nick = gnu | stack = 1

id = a | reason = 광고홍보 | nick = gnu | stack = 2

id = b | reason = 회원기만 | nick = kkk | stack = 1

id = b | reason = 광고홍보 | nick = kkk | stack = 2

id = b | reason = 광고홍보 | nick = kkk | stack = 3

 

 

만약 이렇게 쌓여있고 

stack 이 2인 값을 검색 한다면

제가 원하는 값은

id = a | reason = 광고홍보 | nick = gnu | stack = 2

이렇게 하나만 나오게 하고 싶습니다..

근데 지금은

id = a | reason = 광고홍보 | nick = gnu | stack = 2

id = b | reason = 광고홍보 | nick = kkk | stack = 2

이렇게 b회원까지 나와버립니다.

b 회원은 stack이 3일때 나와야 하는데 말이죠;;

 

 

아래는 징계누적 페이지의 소스입니다.

</p>

<p><?php

$sub_menu = "860010";

include_once('./_common.php');

auth_check($auth[$sub_menu], 'w');</p>

<p>$g5['title'] = '징계';

include_once('./admin.head.php');</p>

<p>$colspan = 8;

$punish_table = 'g5_punish';

// 게시물 ////////////////////////////////////////////////////

$sop = strtolower($sop);

if ($sop != 'and' && $sop != 'or')

    $sop = 'and';</p>

<p>

$stx = trim($stx);

if ($sca || $stx) {

    $sql_search = get_sql_admin_search($sca, $sfl, $stx, $sop);</p>

<p>    // 가장 작은 번호를 얻어서 변수에 저장 (하단의 페이징에서 사용)

    $sql = " select MIN(punish_no) as min_punish_id from {$punish_table} ";

    $row = sql_fetch($sql);

    $min_spt = (int)$row['min_punish_id'];</p>

<p>    if (!$spt) $spt = $min_spt;</p>

<p>    $sql_search .= " and (punish_no between {$spt} and ({$spt} + {$config['cf_search_part']})) ";</p>

<p>    // 원글만 얻는다. (코멘트의 내용도 검색하기 위함)

    // 라엘님 제안 코드로 대체 <a href="http://sir.kr/g5_bug/2922" target="_blank" rel="noopener noreferrer">http://sir.kr/g5_bug/2922</a>

    // $sql = " SELECT COUNT(DISTINCT `wr_parent`) AS `cnt` FROM {$punish_table} WHERE {$sql_search} ";

    $sql = " SELECT COUNT(*) AS `cnt` FROM {$punish_table} WHERE {$sql_search} ";

    $row = sql_fetch($sql);

    $total_count = $row['cnt'];

    /*

    $sql = " select distinct wr_parent from {$punish_table} where {$sql_search} ";

    $result = sql_query($sql);

    $total_count = sql_num_rows($result);

    */

} else {

    $sql = " select count(distinct punish_id) as cnt from {$punish_table} where 1=1";

    $row = sql_fetch($sql);

    $sql_search = "";

    $total_count = $row['cnt'];

}

$page_rows = 25;

$list_page_rows = 25;</p>

<p>if ($page < 1) { $page = 1; } // 페이지가 없으면 첫 페이지 (1 페이지)</p>

<p>

// 년도 2자리

$today2 = G5_TIME_YMD;</p>

<p>$total_page  = ceil($total_count / $page_rows);  // 전체 페이지 계산

$from_record = ($page - 1) * $page_rows; // 시작 열을 구함</p>

<p>// 정렬에 사용하는 QUERY_STRING

$qstr2 = 'punish=punish_sum&sop='.$sop;</p>

<p>// 정렬

// 인덱스 필드가 아니면 정렬에 사용하지 않음

// if (!$sst || ($sst && !(strstr($sst, 'wr_id') || strstr($sst, "wr_datetime")))) {

// sst = 검색정렬필드

// sca = 카테고리

// sfl = 검색필드

// stx = 검색어

// sod = 검색오름, 내림차순

// sop = 검색 or, and 오퍼레이터

// spt = 검색 파트(구간)</p>

<p>if (!$sst) {

    if ($board['bo_sort_field']) {

        $sst = $board['bo_sort_field'];

    } else {

        $sst  = " punish_no DESC"; // 징계횟수 많은순, 징계날짜 최신순

        $sod = "";

    }

} else {

    // 게시물 리스트의 정렬 대상 필드가 아니라면 공백으로 (nasca 님 09.06.16)

    // 리스트에서 다른 필드로 정렬을 하려면 아래의 코드에 해당 필드를 추가하세요.

    // $sst = preg_match("/^(wr_subject|wr_datetime|wr_hit|wr_good|wr_nogood)$/i", $sst) ? $sst : "";

    $sst = preg_match("/^(wr_datetime|wr_hit|wr_good|wr_nogood)$/i", $sst) ? $sst : "";

}</p>

<p>if(!$sst)

    $sst  = " punish_no DESC"; // 신고횟수</p>

<p>if ($sst) {

    $sql_order = "ORDER BY {$sst} {$sod}";

    // $sql_order = " GROUP BY punish_id ORDER BY {$sst} {$sod} "; 2018-05-03 누적징계횟수 group by

}</p>

<p>if ($sca || $stx) {

    if ($sfl == "punish_stack") {

        $sql_where_stack = " "; // 이부분에 where 절을 써서 구분지을수 있을지!?

    }</p>

<p>    $sql = " SELECT * FROM {$punish_table} WHERE {$sql_search} {$sql_where_stack} {$sql_order} limit {$from_record}, $page_rows";

} else {

    /* 2018-05-03 누적징계횟수 group by */

    $sql = " SELECT tt.* 

                FROM {$punish_table} tt

                INNER JOIN

                   (SELECT punish_id, max(punish_stack) AS maxPunishStack

                    FROM {$punish_table}

                    GROUP BY punish_id) groupedtt

                ON tt.punish_id = groupedtt.punish_id

                AND tt.punish_stack = groupedtt.maxPunishStack

                {$sql_order}

                LIMIT {$from_record}, $page_rows

            ";

}

echo $sql;

if ($page_rows > 0) {

    $result = sql_query($sql);

    $i = 0;

    $k = 0;

    $list = array();

    while ($row = sql_fetch_array($result)) {

        $punish_list = array_push($list, $row);

        $list_num = $total_count - ($page - 1) * $list_page_rows;

        $list[$i]['num'] = $list_num - $k;

        $delete_href ='./punish_delete.php?punish_no='.$row['punish_no'].'&token='.$token.'&page='.$page; // 2018-04-27 .urldecode($qstr) 삭제함.

        $list[$i]['delete_href'] = $delete_href;</p>

<p>        $i++;

        $k++;

    }

}

$write_pages = get_paging(25, $page, $total_page, $_SERVER['SCRIPT_NAME'] . '?' . $qstr . '&page=');

////////////////////////////////////////////////////

?></p>

<p><form name="fboardlist" id="fboardlist" action="./board_list_update.php" onsubmit="return fboardlist_submit(this);" method="post">

<input type="hidden" name="bo_table" value="<?php echo $bo_table ?>">

<input type="hidden" name="sfl" value="<?php echo $sfl ?>">

<input type="hidden" name="stx" value="<?php echo $stx ?>">

<input type="hidden" name="spt" value="<?php echo $spt ?>">

<input type="hidden" name="sca" value="<?php echo $sca ?>">

<input type="hidden" name="sst" value="<?php echo $sst ?>">

<input type="hidden" name="sod" value="<?php echo $sod ?>">

<input type="hidden" name="page" value="<?php echo $page ?>">

<input type="hidden" name="sw" value="">

<div class="tbl_head01 tbl_wrap total_punish_wrap">

    <table>

        <caption>누적 신고</caption>

        <thead>

            <tr>

                <th scope="col" class="td_num">번호</th>

                <th scope="col" class="td_id">아이디</th>

                <th scope="col" class="td_nick">닉네임</th>

                <th scope="col" class="td_kind">징계종류</th>

                <th scope="col" class="td_memo">징계내용</th>

                <th scope="col" class="td_datetime">징계기간(일자)</th>

                <th scope="col" class="td_stack">누적징계횟수</th>

                <th scope="col" class="td_note">메모</th>

                <th scope="col" class="td_check">삭제</th>

            </tr>

        </thead>

        <tbody>

            <?php 

                $today = date("Y-m-d");

                for ($i = 0; $i<count($list); $i++) {

                    $bg = 'bg' . ($i % 2);

            ?>

            <tr class="<?php echo $bg; ?>">

                <td scope="row" class="td_num">

                    <?php echo $list[$i]['num']; ?>

                </td>

                <td scope="row" class="td_id">

                    <?php echo $list[$i]['punish_id']; ?>

                </td>

                <td scope="row" class="td_nick">

                    <?php echo $list[$i]['punish_nick']; ?>

                </td>

                <td scope="row" class="td_kind">

                    <?php echo $list[$i]['punish_kind']; ?>

                </td>

                <td scope="row" class="td_memo">

                    <?php echo $list[$i]['punish_memo']; ?>

                </td>

                <td scope="row" class="td_datetime">

                    <?php 

                        $year = date("Y"); // 이번년도

                        $start_year = substr($list[$i]['punish_start_datetime'],0,4); // 징계시작 년도만 ex) 2018

                        $end_year = substr($list[$i]['punish_end_datetime'],0,4); // 징계끝 년도만 ex) 2018</p>

<p>                        $punish_start_year_time = substr($list[$i]['punish_start_datetime'],2,9); // 2018.xx.xx로 변환

                        $punish_end_year_time = substr($list[$i]['punish_end_datetime'],2,9); // 2018.xx.xx로 변환

                        $punish_start_time = substr($list[$i]['punish_start_datetime'],5,5); // xx.xx (월일만)

                        $punish_end_time = substr($list[$i]['punish_end_datetime'],5,5); // xx.xx (월일만)</p>

<p>                        if ($list[$i]['punish_kind'] == "경고" && $year == $start_year && $year == $end_year) { // 경고이고 징계시작과 끝이 같은 년도라면

                            $punish_datetime = $punish_start_year_time."~".$punish_end_time;

                        } else {

                            $punish_datetime = $punish_start_year_time;

                        }

                    ?>

                    <?php echo $punish_datetime; ?>

                </td>

                <td scope="row" class="td_stack">

                    <?php echo $list[$i]['punish_stack']; ?>

                </td>

                <td scope="row" class="td_note">

                    <?php echo $list[$i]['punish_note']; ?>

                </td>

                <td scope="row" class="td_check">

                    <!--

                    <input type="checkbox" value="<?php echo $list[$i]['punish_no'] ?>" name="chk_punish_<?php echo $list[$i]['punish_no'] ?>" id="chk_punish_<?php echo $list[$i]['punish_no'] ?>">

                    -->

                    <a href="<?php echo $list[$i]['delete_href'] ?>" onclick="del(this.href); return false;" id="btnDelete">삭제</a>

                </td>

            </tr>

            <?php } ?>

            <?php if($i == 0 ) { ?><tr><td colspan="8" style="text-align: center; line-height:50px">자료가 없습니다.</td></tr><?php } ?>

        </tbody>

    </table>

</div>

</form>

<?php echo $write_pages; ?>

<div class="btn_wrap">

    <?php if ($stx) {?>

        <a href="./punish_sum.php" target="_self" id="btnList">목록</a>

    <?php } ?>

</div></p>

<p>

<fieldset class="punish_sum_search">

    <form name="fsearch" id="fsearch" method="get">

        <label for="sfl" class="sound_only">검색대상</label>

        <select name="sfl" id="sfl">

            <option value="punish_id"<?php echo get_selected($sfl, "punish_id"); ?>>회원아이디</option>

            <option value="punish_nick"<?php echo get_selected($sfl, "punish_nick"); ?>>닉네임</option>

            <option value="punish_kind"<?php echo get_selected($sfl, "punish_kind"); ?>>종류</option>

            <option value="punish_memo"<?php echo get_selected($sfl, "punish_memo"); ?>>내용</option>

            <option value="punish_start_datetime || punish_end_datetime"<?php echo get_selected($sfl, "punish_start_datetime || punish_end_datetime"); ?>>일자</option>

            <option value="punish_stack"<?php echo get_selected($sfl, "punish_stack"); ?>>징계횟수</option>

        </select>

        <label for="stx" class="sound_only">검색어<strong class="sound_only"> 필수</strong></label>

        <input type="text" name="stx" value="<?php echo $stx ?>" id="stx" required class="required frm_input">

        <input type="submit" value="검색" class="btn_submit">

    </form>

</fieldset>

<style>

    .total_punish_wrap td{text-align: center}

    .td_num{width: 50px}

    .td_id{width: 120px}

    .td_kind{width: 200px}

    .td_nick{width: 120px}

    .td_memo{width: 120px}

    .td_datetime{width: 200px}

    .td_stack{width: 60px}

    .td_check{width: 60px}

    .punish_sum_search {

        margin: 0 0 10px;

        padding: 0 20px;

        text-align: center;

    }

    .punish_sum_search select,

    .punish_sum_search .frm_input,

    .punish_sum_search .btn_submit{

        box-sizing: border-box;

        -moz-box-sizing: border-box;

        -webkit-box-sizing: border-box;

        height: 30px;

        line-height: 30px;

    }

    .punish_sum_search .btn_submit{

        width: 80px;

    }

    #btnList{

        display: inline-block;

        width: 50px;

        height: 30px;

        line-height: 30px;

        text-align: center;

        background: #e2e2e2;

    }

    .btn_wrap{

        margin: 0 0 10px;

        padding: 0 20px;

        text-align: right;

    }

</style></p>

<p><?php

include_once('./admin.tail.php');

?>

 </p>

<p>

 

 

 

댓글을 작성하려면 로그인이 필요합니다.

답변 3개

채택된 답변
+20 포인트

검색 조건이 확실하지가 않네요

stack = 2 인 사람을 검색한다면 2개가 나오는게 맞습니다. 검색 조건이 회원의 마지막 징계리스트를 구하는 것이라면

select b.* from

(select mb_id, max(stack) as stack from A_table group by mb_id) as a

left join A_table as b on a.mb_id = b.mb_id and a.stack = b.stack

이정도 되지 않을까요??? 에러나려나??? 테이블자료가 없서서 실행해 보지는 못하네요ㅠㅠ

 

이것은 2가 마지막인 사람

select b.* from

(select mb_id, max(stack) as stack from A_table group by mb_id having stack = '2') as a

left join A_table as b on a.mb_id = b.mb_id and a.stack = b.stack

로그인 후 평가할 수 있습니다

답변에 대한 댓글 2개

l
lacomparte
7년 전
[code]
SELECT b.* FROM
(SELECT punish_id, max(punish_stack) AS stack
FROM g5_punish
GROUP BY punish_id
HAVING punish_stack = '2') AS a
LEFT JOIN g5_punish AS b on a.punish_id = b.punish_id AND a.stack = b.stack
[/code]

having 절이 에러가 나는 이유가 뭘까요;;
l
lacomparte
7년 전
소스 알맞게 수정해서
적용했습니다.

감사드립니다 ㅎ

댓글을 작성하려면 로그인이 필요합니다.

l
7년 전

테이블 이렇게 생겼습니다

 

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

l
lacomparte
7년 전
이 자료를 바탕으로
사용자가
sfl 을 punish_stack 으로 두고
2를 검색하면
결과 값이 없어야 하고,

3을 검색하면
punish_no 24인 값만 나오면 될것 같습니다...


댓글을 작성하려면 로그인이 필요합니다.

Policia
7년 전

이럴땐 해당 테이블내에서 중복갯수를 구하는 쿼리를 이용하시면됩니다

 

select *,count(*) from 테이블명 group by id having count(*)=검색숫자

 

group by로 중복되는 id값들을 묶어주고 해당 id에 대한 테이블에서 스택갯수를 구합니다

 

그럼 count(*)에 몇번 신고가되었는지 집계가 될것이고 count(*)를 통해서 검색시 숫자를 집어넣어 카운트가 2개인것만 찾으면 되는겁니다

 

라고 생각하긴했는데

 

스택이 초기화될 경우도 있겠다 싶어 (기록은남고)

 

select * from 테이블명 where stack=검색시숫자 group by id

이런식으로 하시면 가장 최근 값만 남기고 합쳐지니 될것같습니다

 

초기화되는 경우가 아니면 위쪽이 좀더 정확하겠네요

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

유레카56
7년 전
아마 말씀 하신 쿼리르 작성 하신다면
id = a | reason = 광고홍보 | nick = gnu | stack = 2

id = b | reason = 광고홍보 | nick = kkk | stack = 2
와 같은 결과가 출력 될꺼에요 group by id로 묶인 kkk 값에 stack 이 2인 값이 있기 때문에 해당 내용에 관해서는 윗분이 적어주신 서브쿼리를 이용한 방법이 가장 괜찮아 보입니다.

댓글을 작성하려면 로그인이 필요합니다.

답변을 작성하려면 로그인이 필요합니다.

로그인